The Fall Tutorial
The Fall Tutorial
Disclaimer
Please note that any manipulation done to files or any other data is at your own risk. You should
make a copy of every file you may work on. Any changes made to a file could destroy your The
Fall installation.
Every information or tool contained in this tutorial is used at your own risk. There are no
guarantees or warranties stated or implied by the distribution of this information or the
corresponding tools. Use this tutorial and the tools at your own risk. Any damage or loss
resulting from their use is the sole responsibility of the reader.
The tools and information may contain errors, problems, bugs or other limitations. We assume
no liability or responsibility for any such errors, problems, bugs or limitations. We also assume
no liability or responsibility for any errors, problems, bugs or limitations caused by using this
tutorial.
In no event shall Silver Style be liable for any special, indirect, incidental or consequential
damages arising out of the use of tools or information contained in this tutorial. In all other
circumstances, Silver Style‘s total aggregate liability to you or any third party, however arising,
shall be limited to $15.
“Come closer ... Yes you, Siv.
Ah, look at this posture, strength and spirit, excactly what I'm looking
for. Let me ask you just one thing: Do you wanna feel like a god?
Create your own world controlled by your rules, your people, your
own history and future? Do you wanna create virtual life? 'Cos that's
what I'm offering; nothing more, nothing less.
Ever had a dream or an idea that you would like to share with others?
Tell your story in a playable way? Then follow me into this humble
tutorial on creating your game with The Fall. Create a map with the
built-in editor. Add your objects to this world and give them functions.
Create your heroes, villains and normal folks, make them act, fight
and tell your story.
All it needs is a little (or all) of your time ...“
“If that's really all? Nah, no deal is that perfect. Of course it takes
some more general tools and skills, but someone like you has them at
his fingertips. Aeh?“
Table of contents
MODDING THE FALL.......................................................................................................................1
Disclaimer ........................................................................................................................................1
Table of contents..................................................................................................................................3
Introduction..........................................................................................................................................7
The Directories, the Files and the Extentions ..................................................................................8
The Directories.............................................................................................................................8
The Files.......................................................................................................................................8
The Extentions .............................................................................................................................8
'.ubn' .........................................................................................................................................8
'.py' and '.pyc' ...........................................................................................................................9
'.fx'............................................................................................................................................9
'.gui' and '.lay' ...........................................................................................................................9
'.png' and '.dds' .........................................................................................................................9
'.diff3d' .....................................................................................................................................9
'.grid_map'................................................................................................................................9
'.ogg' .........................................................................................................................................9
'.bik' ..........................................................................................................................................9
'.zip' ..........................................................................................................................................9
'.gr2'........................................................................................................................................10
Snake Charmer: Scripts and Basic Structure .................................................................................11
The Scripting Language Python.................................................................................................11
Plain Script and Bytecode ..........................................................................................................11
Basic Structure ...........................................................................................................................11
Nobody's Perfect: Debugging Python ............................................................................................13
The Console ...............................................................................................................................13
Tracefile .................................................................................................................................13
The Module Debug ....................................................................................................................13
The Command Reload ...............................................................................................................13
Maps, Objects, Textures and Sounds .................................................................................................15
Creating a Map with the Built-in-Editor ........................................................................................16
Getting Started ...........................................................................................................................16
Creating a Height Map...............................................................................................................16
Using the Height Map in the Editor ...........................................................................................17
Objects .......................................................................................................................................19
Textures......................................................................................................................................20
Ground Data...............................................................................................................................21
Experiment .................................................................................................................................22
Shortcuts.....................................................................................................................................22
Adding a New Object: 'Hey, That's my Red Cube There!' ............................................................24
Building an Object .....................................................................................................................24
Exporting an Object ...................................................................................................................24
Placing an Object in the Right Game Directory ........................................................................25
Registering an Object in the Game ............................................................................................25
Ground Data for Objects ............................................................................................................26
No Ground Data .....................................................................................................................26
Generic Ground Data .............................................................................................................26
Special Ground Data ..............................................................................................................27
Textures and UI Elements..............................................................................................................28
The Textures ..............................................................................................................................28
Convert to DDS......................................................................................................................28
Registering UI Elements (Adding a New Location to the Map)................................................28
GUIResourceData ..................................................................................................................29
Layout Manager .....................................................................................................................30
Sounds............................................................................................................................................32
Format ........................................................................................................................................32
Directories and Files ..................................................................................................................32
Effect Sounds .........................................................................................................................32
Speech Files ...........................................................................................................................32
Registering Sound Effects..........................................................................................................32
Scripting Sounds ........................................................................................................................32
Sound Effects .........................................................................................................................32
Speech ....................................................................................................................................33
Scripting .............................................................................................................................................34
First Steps: 'Dear Diary: Today I Met ...' .......................................................................................35
The Meeting ...............................................................................................................................35
Dictionaries and Lists.............................................................................................................35
Her First Words..........................................................................................................................36
Define a Function...................................................................................................................36
Understanding Events ............................................................................................................36
Using the Event on_approach()..............................................................................................37
The Command reload() ..........................................................................................................37
Hunting.......................................................................................................................................37
The Event on_map_loaded.....................................................................................................37
Attributes................................................................................................................................38
Another Event Example .........................................................................................................38
Passing Parameters to a Function...........................................................................................38
Using Debug Cheats...............................................................................................................38
Getting the Meat.........................................................................................................................39
Finding Information About Items ..........................................................................................39
Event Groups..........................................................................................................................39
Updating Code to Full PC Group...........................................................................................40
The Second Dimension: Time....................................................................................................40
Callbacks................................................................................................................................40
Lambda...................................................................................................................................41
Understanding the Zone Structure .................................................................................................43
A Zone‘s Directories and Files ..................................................................................................43
Base Name, Directory and Module........................................................................................43
Files and Directories in the Zone Directory...........................................................................43
Events.........................................................................................................................................43
Event Prefixes and Types.......................................................................................................44
Some Main Events .................................................................................................................44
Activating a Zone...........................................................................................................................46
Preparing the Travel Map ..........................................................................................................46
Setting Location Name...........................................................................................................46
Other Global Lists......................................................................................................................46
Sky Color ...............................................................................................................................46
Resting Place..........................................................................................................................46
Activating Respawn of Animals ............................................................................................47
Enabling a New Zone.................................................................................................................47
NPCs: 'A New Star is Born' ...........................................................................................................48
Basic Creation ............................................................................................................................48
Party .......................................................................................................................................49
Clothes ...................................................................................................................................49
Faces.......................................................................................................................................49
Faction and Level...................................................................................................................49
Special Commands to Control NPCs .........................................................................................49
Active .....................................................................................................................................49
Immortal.................................................................................................................................49
Approachable .........................................................................................................................50
Daily_routine commands .......................................................................................................50
Foes ........................................................................................................................................50
Scale .......................................................................................................................................50
Equipping NPCs.........................................................................................................................50
Items.......................................................................................................................................50
Weapons.................................................................................................................................50
Player Characters .......................................................................................................................51
Face and Hair .........................................................................................................................51
Voice_id .................................................................................................................................51
ID Card...................................................................................................................................51
All Talk: Scripting Dialogs ............................................................................................................52
Small Dialog ..........................................................................................................................52
Large Dialog ..........................................................................................................................52
Registering Text IDs ..................................................................................................................52
Dialog Choices and Branches ....................................................................................................53
Auto-Deactivation and New Choices.........................................................................................53
Removing an Additional Dialog Choice from a Running Dialog..............................................53
Alternative Starting Line............................................................................................................54
Daily Schedule: 'Everyone Has to Make a Living' ........................................................................55
The Dictionary Schedule............................................................................................................55
ID of NPC ..............................................................................................................................55
List of Schedules ....................................................................................................................55
Dictionary of Timeframes......................................................................................................55
Dictionary in a Timeframe.....................................................................................................55
List of Functions ....................................................................................................................56
Commands to Control Schedule Behavior.................................................................................56
The General Work Flow of NPC Actions..............................................................................56
'allow/prohibit activity'...........................................................................................................56
'on wait for commandos' ........................................................................................................56
Using Schedules.........................................................................................................................56
Basic Timeframe ....................................................................................................................56
Continue Loops ......................................................................................................................57
Start/Loop Sets and Intelligent Functions..............................................................................57
Dialogs Defined in Schedules ....................................................................................................57
Basic Time-dependant Dialogs ..............................................................................................57
Gender-specific Dialogs.........................................................................................................58
Long Dialogs..........................................................................................................................58
Specials ..............................................................................................................................................59
Items: 'I Need Guns ...' ...................................................................................................................59
Creating the 3D Object ..............................................................................................................59
Effect Dummy........................................................................................................................59
Two Objects in One Mesh .....................................................................................................59
Positioning the Object............................................................................................................59
Adding the Icon..........................................................................................................................60
Scripting .....................................................................................................................................60
'objectdata\items' ....................................................................................................................60
'itemdata' ................................................................................................................................61
Linking Special Scripts ..............................................................................................................63
Weapon Events ......................................................................................................................63
Special Functions for Using Items .........................................................................................63
Creating a Mod Package ................................................................................................................64
The Structure..............................................................................................................................64
Convert PNG to DDS.............................................................................................................64
The Module Startup ...................................................................................................................65
Addressing Mod Files ............................................................................................................65
Startup: Place Statements Only in Functions.........................................................................65
The Function mod_init...........................................................................................................65
Introduction
The Fall offers many possibilities to create your own story. From changing the existing campaign to
creating a completely new one. From maps over importing objects, textures, sounds to scripting
NPCs, dialogs, story and action – everything can be done.
But such possibilities need a lot of explanation and skill. So do not let the size of this tutorial scare
you and remember: to create a game it always takes a team. Learn and understand the part that most
appeals to you and find friends who do other parts. Working as a team is always more fun.
The first 3 subchapters contain real basics. You will need them for nearly every aspect of your
creation. They will tell you how to unlock The Fall’s files and how to change entries in the Python
scripts. You do not need to learn programming, you just need to know how to find the right spot and
add an information field for your new map, object, sound or texture. If you are a programmer, these
chapters might be too easy for you, but they are short, so it will not hurt to risk a look.
The next big chapter explains objects, textures, sounds and maps. You might say that this is up to
the artist. But do not misunderstand me, I will only explain what can be imported into The Fall and
how this can be done. How to create the material itself is covered by tutorials all over the web.
The second big chapter is about scripts. Scripts hold everything together and define the story. Many
aspects of the game depend on scripts, like NPCs, dialogs, schedules, plot and action. You do not
know Python? Don’t worry; if you know any programming language, you will learn Python in a
day.
The last chapter covers more complex topics and is for cracks or those who became ones while
working with the other chapters. Here you will learn how to create a usable object or a mod
package.
The Directories, the Files and the Extentions
The Directories
Most directories in The Fall are compressed into handy archives. You can easily indentify them by
their extension '.ubn'. These are standard ZIP-archives, which can be decompressed using the
corresponding tools.
For example the file scripts.ubn:
Open your ZIP-tool, select scripts.ubn, then hit 'decompress', or select scripts.ubn and click on
'decompress' in the context menu (you may need to register '.ubn' with your ZIP-tool). Now select
the game root directory (e.g. 'The Fall Last Days Of Gaia') and decompress the files there. After
this, there should be a new subdirectory in your game directory called 'scripts'.
The Fall will now load the files in the uncompressed directory the next time the program is started.
However, there are constellations where this might not work properly:
If the program has difficulties loading your changed files from the uncompressed directories, then
replace the corresponding '.ubn'-file with an empty archive of the same name (as always, NEVER
forget to back up before deleting or changing any game files).
The Files
Each directory contains a special set of information:
• 'data': Mostly information about masks for panels and graphic effects.
• 'gui': Textures for panels and controls (needs mask information from data).
• 'objects': All models.
• 'scripts': Global scripts and texts.
• 'sounds': All sound effects (except speech).
• 'speech_english': Global speech samples.
• 'terrain': Textures for terrain and sky.
• 'textures': Textures for models (objects).
• 'video': The cinematics.
• 'zones': Scripts and texts for zones.
• 'zone_speech_english': Speech samples for zone dialogs.
• 'zone_speech_english2': More speech samples for zones; keep the directory structure
'zone_speech_english2\zone_speech_english\....' as it is.
The Extentions
'.ubn'
Look above in chapter: 'The Directories'.
'.py' and '.pyc'
These are python script files in plain text (.py) or as bytecode (.pyc). At every start, The Fall turns
all changed python files into bytecode files. For more information on scripting go to chapter:
'Scripts and Basic Structure'.
'.fx'
Data on graphic effects.
'.diff3d'
3D-models (except persons/animals); these hold the wireframe and the texture's path/name of an
object. See chapter 'Adding a new Object' for more.
'.grid_map'
Defines the ground occupied by objects in the game. Also see chapter: 'Adding a new Object'.
'.ogg'
Sounds in OGG Vorbis. Chapter 'Sounds' covers this topic.
'.bik'
Video files.
'.zip'
The zone maps (of course only '.zip'-files in the game directory). See chapter 'Creating a Map' for
more information.
'.gr2'
Objects animated with Granny 3D. An export filter is not freely available.
Snake Charmer: Scripts and Basic Structure
Basic Structure
There are two main directories for Python scripts in The Fall:
• scripts: Contains all global scriptings.
• zones: Devided into different zones; contains the local scripts for each zone.
Modules found in scripts and zones can be imported into the game. This includes packages like the
information for a complete zone. For instance, to address the main script in zone_1 you need to
import the package zone_1 and then the module for that particular package: zone_1.zone_1.
Let me give you a short explanation of import and namespace. Let’s say we want to use the
functions defined in the module global_defines. One way is to use 'import global_defines', then
every function is addressed as 'global_defines.function'. The other way is to use 'from
global_defines import *', then a function there would be addressed as 'function'. The same goes for
packages like 'zone_1'.
All commands provided by the engine are imported and addressed in the same way. Every
command available and most modules and routines in the script directory are explained in the API
documentation. Find the Application Programming Interface in this package or at:
http://www.the-fall.com/mod-doc/
http://www.the-fall.com/mod-doc/mod-doc.zip
Nobody's Perfect: Debugging Python
The Console
During the game, the key 'F11' opens the console. This is an input line for the Python command
interpreter and above it you can find a text screen listing all prints, bug messages and command
responses.
Every Python command and every function call to our engine can be given via this console. Start
functions for a test run, check variables, cheat items, do everything normally done with script code
instantly.
The Python command print can display strings and most variables in the console and tracefile. It is
a good way to check code flow and variable values at critical game situations. Even exceptions
(script bug) print a detailed report.
Tracefile
Every print and other system message is writen into the file tracefile.log in your The Fall
configuration and savegame directory. To find it in Windows, use the following source name in the
explorer: '%APPDATA%\Silver Style Entertainment\The Fall - Last Days of Gaia'.
At every start of The Fall, the tracefile is overwritten with a new one. So make copies if you need
the information contained in it at a later time.
Bugs in objects, maps and textures can often cause a termination of the program. The only way to
get information about these errors is the tracefile. But the game-exe is compiled without additional
debug information, so do not hope to get much information there.
Welcome to the artist's way. If you did not read the introduction, now might be the time to read at
least the chapters 'The Directories, the Files and the Extentions' to learn how to find the different
files. But maybe you have already figured this out yourself, then just read on.
The first chapter explains the editor in greater detail. All tools are covered, plus some basic tips.
However, the next three chapters after that only explain how to implement material into The Fall.
To find tutorials about creating objects, textures and sound, just search the web. There should be
plenty of good ones around.
The chapter Objects covers objects for the editor, but no equipable items. Textures just need to be
placed in the right directory; only UI-elements need additional information. The chapter Sounds is
even shorter, because only the sound effects need a special list entry.
Creating a Map with the Built-in-Editor
Getting Started
In The Fall a region/level is called a 'zone'. A zone contains a map, scripts and local dialog texts. To
work properly in the game, the zone has to be placed in the directory zones inside the games
directory. Create a directory there with the name of your project. For this tutorial we will just call it:
tutorial_map.
Now the zone directory should look like this: '\\The_Fall\\zones\\tutorial_map'. Remember to save
your zone in the directory under the same name:
'\\The_Fall\\zones\\tutorial_map\\tutorial_map.zip'.
The map must be created inside this directory, because the editor uses the directory structure to
create the IDs for the objects placed on the map. Creating the map somewhere else and just moving
it to the right directory later on, might cause problems and will make scripting somewhat more
difficult.
For more information about directory structure, see chapter 'Introduction'.
Yeah, not much, so on to the next step. Take your smudge tool and blur the lines with random
strokes. Start on the line and move out a small distance in random directions. Repeat till the lines
have a smooth transition to the surrounding grey. But do not try to make it perfect – it needs this
random touch to make it look natural.
The result is still not the real thing, but good enough for 10 minutes work (the picture
'tutorial_heightmap2.png' can be found in this package). It is essential to get a feeling for how color
corresponds to height and how smooth but still rough it needs to be in order to look natural.
Also, this is only one way to create smooth but random transitions; try your own ideas.
The upper two fields labeled 'Scale' control how color is converted into height; the first field stands
for black and the second for white color. Leave them at 0-25 m for the moment.
The field labeled 'Path' takes the address of your image. You can select the image by clicking on the
'Browse' button. Now click OK and look at the world you have created.
When you want to edit your height map again, just select 'export height map' from the same menu
to save a new PNG-picture representing the actual height map information. This is needed when the
original picture is not available or when the height map is changed in the editor (see 'equalize').
Objects
Now take a closer look at the left panel; in the upper left corner is a preview area that will show an
image of the selected object, if available. Below it is the selection tree holding all available objects
and textures divided into four groups: 'Base Texture', 'Objects', 'Textures' and 'Underground Path
Data'.
It is time to place your first object: click on 'Objects' in the selection tree. A list of object classes
opens up. Also the editor is now set to 'Objects' mode; this means that we can select objects, but
cannot select textures. In order to change to 'Texture' mode click on 'Textures' (more information
about textures later).
Now click on 'Village Houses' and select a house you like. Then place it on the map by just clicking
on the target area. Click on the placed house to select it. It should turn red. Click and hold again to
move the object around.
Have you noticed the new button row now visible below the menus? This button row lists all
available actions for objects:
To place the next object from the selection tree click on the 'Insert' button and then place the object
on the map with the next click. To select another object click on 'Select' and then on the object on
the map. Now move it around by clicking on 'Move', click and hold and move it around. Next click
on 'Rotate', click and hold again to turn the object around.
You can change the scale of an object by clicking on the 'Scale' button, click and hold and move the
mouse up and down. All objects that characters interact with like houses, furniture, etc. need a fixed
size and cannot be scaled. However, trees, stones and other objects can be changed in size.
Big objects need a flat ground for placement. To level the ground use the 'Equalize' function. Just
select the object and hit the 'Equalize' button. You get more control over this function by opening
the 'Equalize' window: select 'View'->'Show Equalize Settings' from the menu.
The left slider controls the height of the levelled ground. Moving the slider to the left sets Equalize
to the lowest occupied ground. Changes only take effect with the next hit of the 'Equalize' button
and you cannot equalize a changed ground again. So, always use 'Undo Last Equalize' after every
try that is not perfect.
When more than one object is selected, all objects will be equalized to the same height, with min
and max being extended to all objects. To equalize a group of objects separately hold ‘Shift’ while
equalizing.
Use 'Q' and click somewhere to find nearby objects that still need equalizing.
Most houses have an interior, which you can access by clicking on 'Interior'. This removes the roof
of the house; all objects placed now become part of the house. Only place objects inside the house,
it would look strange to have a table outside the house that is only visible when someone enters the
house (which switches the house into Interior mode).
Objects that you do not need anymore can be deleted with 'Delete'. If you want to replace an object
that is used by script first write down its ID. Then delete it and replace it with the new object. Now
give this new object the old ID by clicking on 'Identifier' and entering the old ID.
It is up to you to experiment with these functions, and you will see that every info was worth
reading it. But let me add some final tips:
− Too many objects can hamper performance; use enough objects for atmosphere, but do not
overdo it.
− Objects cannot be placed 'inside' the ground. Do not place objects overlapping each other, as this
may cause texture flicker.
− To search for objects select 'View' under 'Menu' or press 'CTRL + L'. The first object found
containing the searched word is selected. Go to all objects found with 'Next' and 'Previous'.
Textures
In The Fall all objects are fully textured. The only thing left to do is to texture the ground. Let’s
start with changing the base texture: Select 'Base Texture' in the selection tree and pick 'Red Desert'.
Next take a stone texture to cover the steep hillside. You will find it in 'Texturen'->'FOLDER
ROCKS' ->'Redrock rot'.
Now move it around and turn it like you did with the objects. Scale works on two axes by moving
the mouse left/right or up/down. You can also 'Flip' or 'Mirror' the texture until it fits into place.
Place more texture around it to make it look like a broken, rocky hillside. When placing textures
close or overlapping, you may need 'To top' and 'To back' to control which textures you see and
which not.
There are no general rules to give here, just the advice to look at every creation from all sides and
different distances. Scaling textures can be a tricky beast – better do not scale up; most times it will
look grainy.
Ground Data
The Fall uses a grid structure to mark blocked ground. Press 'T' and look around. Most objects have
green tiles beneath them, showing the ground they block for movement. The space needed for an
object is always rounded up to full tiles.
Try to place small objects in the middle of tiles, so that they block less tiles. And pay special
attention to doors, fences and objects standing close together: Make sure that there is still a tile free
between them, so that characters will be able to pass through there.
Objects that NPCs interact with have dummies marking the place the character will move to. Such
places should also be accessible, but do not worry about the ground covered by the object itself, the
person send to the object will ignore this specific tile. Press 'M' and click on an object to view its
dummies.
To intentionally block areas like steep mountainsides click on 'Underground Path Data' in the
selection tree. Select a brush and paint the blocked area with red tiles.
Experiment
Now it is up to you. Play around, use what you find and talk to others about it. A forum is always a
good way to discuss, learn and teach. Have Fun.
Shortcuts
New map ('KEY_CTRL', 'KEY_N')
Fullscreen ('KEY_F')
Delete ('KEY_DELETE')
Identifier ('KEY_I')
Help ('KEY_F3')
Select ('KEY_F2')
Move ('KEY_F3')
Rotate ('KEY_F4')
Scale ('KEY_F5')
Equalize ('KEY_E')
First, I need to say, that I cannot explain here how to build objects with 3D programs. That would
be way too much for a specific modding tutorial.
We are using 3DS Max here and the following shots were made with this program. As these
pictures show only two configuration masks, it should not be too difficult to make the same
adjustments in your favored 3D tool.
Building an Object
For start, the object has to be of the type 'editable poly' or 'editable mesh'. To control the size of the
object in the game set the unit size to 'centimeter'.
The texture is saved in a separate file and has
to be set in the fields 'Diffuse Color' and
'Opacity'. Just select your texture; path
information does not matter for now.
Now you are set to create your item. If you
need help here, just search the internet; there
will be plenty of tutorials, texts and forums
about designing 3D-objects.
Make it an object to be placed on the map for
now, because usable items will be explained
later in the chapter Items: 'I need guns ...'
Meet me back in the next chapter for exporting the object into the game format.
Exporting an Object
We will need the Diff3D converter for this, so get it from this package or at:
http://www.the-fall.com/mod-doc/ConvertToDiff3D.exe
The first step is to export your new object
into the ASCII Scene Export format
(.ASE). Activate the following options
(picture to the right):
'Mesh Definition', 'Materials', 'Transform
Animation Keys', 'Animated Mesh', 'Mesh
Normals', 'Mapping Coordinates',
'Geometrics', 'Helpers'.
Then convert the '.ASE'-file with the
converter ConvertToDiff3D.exe.
Use the following options:
ConvertToDiff3D -map -man -mat example.ase
Placing an Object in the Right Game Directory
All objects need to be placed in the directory 'objects'. You can look up all existing objects in the
file objects.ubn. As described in the previous chapters 'The Directories', 'the Files and the
Extentions' this is a zip archive containing the directory objects.
You do not need to decompress this directory because The Fall checks the directory objects and the
file objects.ubn for registered objects. But it should be easier to place your new object in the
uncompressed game resources because you can see the existing directory structure and do not need
to recreate it. Also, your object needs a unique name, so you will have to check the objects archive
whether your desired name is still unused.
The directory 'objects' holds the following sub-directories:
− 'additionals\thefall': All weapons, items (directory 'misc') and quest items (directory 'quest')
are placed here. You will learn more about these items in the chapter Items: 'I need guns ...'
− 'animals': Contains all animals.
− 'buildings': Here you can find all objects that can be placed on a map via the editor (except
vegetation).
− 'characters': Contains all character models (they cannot be created, because the Granny 3D
exporter is not free).
− 'vegetations': Same as 'buildings' but for vegetation.
− 'vehicles': Contains the vehicle models.
As your first item should be a map item, it goes into 'buildings'. Create a new directory in there and
place your object file in the directory (the converted Diff3D version of course).
Now for the texture of your new object. This is similar to placing the object but do not create a new
directory in 'textures\buildings\', just place your texture in the existing directory. For more
information about textures, see the next chapter 'Textures and UI Elements'.
The name does not really matter, but to identify its content at a glance it is better to start the ID with
a special name. For buildings this is 'RES3D_TRES_OBJECTS_BUILDING_' (or 'RES3D_').
Now set the attributes for this data set:
objects.set_attributes( object_id='RES3D_TRES_OBJECTS_BUILDING_EXAMPLE',
diff3d_file = "objects\\buildings\\furnishing\\example.diff3d",
height = 2.000,
transparency = 1.0,
editor_directory = "TRES_OBJECTS_FOLDER_KLEINOBJEKTE",
preview_file = "gui\\previews\\buildings\\example.png",
map_type = MT_NONE,
)
These attributes stand for:
− 'diff3d_file': The path identifying your new object (starting after main game directory).
− 'height': This represents the height of the object as used for line-of-sight calculations. This is
independent of the visual height of your object, which you set during object creation.
− 'transparency': Also for line-of-sight; defines whether one can see through the object. 1.0
means solid, 0.5 is good for fences and 0.0 stands for invisibility.
− 'editor_directory': For organizing objects in the editor’s directory structure.
− 'preview_file': Also for the editor: Defines a PNG-picture as preview when selecting this
object in the editor.
− 'map_type': MT_NONE states that no ground is blocked by this item, so that NPCs could
walk through it. See next chapter below.
That’s it, your very own object usable by the editor. OK, it is not yet in the campaign, but that is
another topic. Start the editor and place your object somewhere or read about the editor in the
chapter 'Creating a Map'.
No Ground Data
To set no ground data use:
map_type = MT_NONE, # as part of the above set_attributes command
or:
objects.set_attribute(object='RES3D_TRES_OBJECTS_BUILDING _EXAMPLE',
attribute="map_type", value=MT_NONE)
# as stand-alone command
You can still paint the ground blocked in the editor. See chapter 'Ground Data'.
The Textures
Format
The base picture must be a 32 bit PNG picture (24 bit color, 8 bit alpha). Also, the dimensions of
the picture need to be a power of two ( ..., 512, 1024, ...). No other specifications.
Convert to DDS
A new DDS file is only created, when there is no DDS file for an existing PNG picture. So delete
the DDS file if you changed the PNG picture. Also, as described in the chapter 'The Directories'
unpack the textures.ubn and gui.ubn und replace them with empty ZIP files, to make sure that the
changed picture is used.
But do not convert the files to DDS yourself. The Fall can load the PNG files and use them. It can
also convert and save the DDS version automatically if an additional tool is installed.
This tool can be found in this tutorial package or at:
http://www.the-fall.com/mod-doc/png2dds.zip
Unpack the file and place it in your The Fall main directory. At the launch of the game, all
directories are checked for pictures to convert to DDS. Normally this is done only at first launch a
day and takes quite some time.
The converter extracts the format from existing DDS files in a directory and transfers other PNG
pictures into this DDS format. A PNG picture in a directory without any DDS picture might cause a
convert error.
following view:
The button marked with the red 2 imports the texture file. Only imported textures can be used in the
element dialog. You could use an additional texture for your new elements, but it is easier to add
your new icon to the existing map panel texture.
The button row marked with the red 1, controls the resources:
− Upper button: Creates a new resource entry.
− Middle button: Copies an existing entry.
− Lower button: Deletes an entry.
Press the upper button to create a new entry. Select it and change its ID and name ('Bezeichner') in
the fields above button row three. Use a unique ID in the same range as the other entries; the name
of your element should also be unique but is only used as description here.
Now define an element with the button row marked with the red 3:
− 'Neuer Bereich...' - Creates a new entry.
− 'Bereich bearbeiten...' - Changes an existing entry.
− 'Bereich löschen' - Deletes an entry.
− 'Bereich kopieren' – Copies an entry.
Click on the button 'Neuer Bereich' and get the following dialog window:
The fields named 'X1', 'Y1', 'X2', 'Y2' take the coordinates of the icon on the texture. The fields
'width' ('Breite') and 'height' ('Hoehe') display the dimensions of the icon; use these sizes later in the
layout manager.
Select the texture file under 'Textur' and leave the other four fields as they are.
Take a note of ID, width and height to use in the layout manager.
Layout Manager
Start the layout manager and open the file:
'main_directory'l\gui\gui_mission\mappanel.lay.
Start a new entry by clicking on and holding the white field and
drawing a box.
Now edit the fields:
− 'Bezeichner': Name of the entry (see below).
− 'ID': Number of the element in this layout.
− 'X1,Y1': Upperleft coordinates of the box.
− 'Breite, Höhe': Dimensions of the box; need to be identical to the
ones set in GUIResourceData.
− 'GUI Ressource Id': ID set in GUIResourceData.
− 'Text Id': Not used in The Fall.
Enter the name of the new zone in The Fall’s scripts and add a prefix:
− 'IM_': Image; mark your icon this way.
− 'FD_': Field; the click sensitive area for this icon.
− 'CP_': Placeholder for texts (no new ones possible).
− 'BT_': Button: Place of buttons (no new ones possible).
The image entry needs to have the exact dimensions and ID set in
GUIResourceData. The click field only needs the right name, but do
not overlap it with other click fields. The other two field types cannot
be added, at least there is no way to give them functionality.
Now visit chapter 'Activating a Zone' to learn more about the script part for a new zone.
Sounds
Format
The sound files need to be OGG Vorbis with reasonable sampling rates.
Effect Sounds
The sounds for effects can be found in the directory 'main_directory'\sounds\ingame. They have to
be added to the sound list (see further down).
Speech Files
There are three main directories for dialogs:
− 'main_directory'\speech_english\globalsmp: Global speech.
− 'main_directory'\zone_speech_english: Speech registered in zones.
− 'main_directory'\zone_speech_english2: As above, only divided for installer reasons.
Scripting Sounds
Sound Effects
The commands to play sounds can be found in the module sounds.
Speech
The engine plays the speech with the same ID as the dialog. Female player characters have the
prefix 'aef_' and mercenaries the prefix 'mercenary_name_'.
Scripting
In the following chapters I will explain how to create a new zone and fill it with content. The first
chapter starts at zero and builds up example content. The other chapters are just collections of
information. Maybe boring to read, but full of details.
Remember, most times it is easier to modify existing code than to build something from scratch.
And here is where abstraction and autodidaction starts. Look at the scripts, existing objects, maps,
etc.
Start with the chapter 'First Steps', maybe even go through the topics that interest you most right
now, but be sure to experiment with existing material while or even before trying to build
something yourself.
Always remember: If you are stuck with your new zone, go back to experiment with
modding/reading an existing zone. If you cannot get a hold on existing code, then (re)read that
specific part of the tutorial and try to build it yourself.
And never forget the forum: Ask questions about what you cannot find out yourself and teach
others the things you understand.
First Steps: 'Dear Diary: Today I Met ...'
This really is a 'work with me' part of the tutorial and it will guide you through the first steps of
scripting. Let’s start with some preparations:
The zone for this tutorial is provided as a mod. Look for the directory 'mods' in your The Fall main
directory. If you cannot find the mod tutorial_mod in there, just unpack the tutorial_mod.zip
provided with this tutorial and place it in The Fall’s main directory (directory structure
mods\\tutorial_mod saved in zip file).
Next, you will need your code editor. Visit www.python.org for a nice overview. Open the code
editor and open all .py-files found in mods\\tutorial_mod\\mod_1. These are all script files that
define the tutorial zone. To make it easier, I placed all scripting examples for this tutorial as
comments into them. Just find the lines for the chapter you are currently reading and uncomment
them. That is, if you do not want to write them yourself.
#This is a comment; just delete the '#' to make a normal command out of it
It is always handy to have additional code examples, so if this interests you just unpack the
scripts.ubn and zones.ubn (see chapter 'The Directories') and you will have all Python code used in
The Fall at hand.
And do not forget the API. It can be found in this package or at http://www.the-fall.com/mod-
doc/mod-doc.zip
Also, it is easier to switch tasks between the running game and your code editor when the game is
running in window mode. So change this in the external options and also set a low resolution.
The last step is to activate the mod in the ingame options. Open 'Options' in the 'Startmenu' and set
'Use modification 'tutorial_mod' ' to on. You need to restart The Fall if you change mod options.
Now press 'Start' (yes, the button to start a campaign) and see your Alter Ego standing in a desert.
The Meeting
It is really boring standing there alone in the desert, so let's script some company. Open the file
npc.py (with your code editor) in the mod_1 zone (mods\\tutorial_mod\\mod_1\\npc.py) and look at
line 33ff:
Now we have one dictionary npcs = {'name' : [..]} with the entry named 'FEMALE' and a list [..] of
information. The entry name will be the ID of the new NPC and both names have to be unique (in
their namespace) so change 'FEMALE' into 'NPC_1'.
The NPC would be created on the same spot as your player character, so better place her a few
meters away by changing her x,y position: ... ,300, 305, ... Give her a new name: Just replace
globaltext.M_NAME_FEMALE with 'girl'.
Npcs = {
'NPC_1':['female', 'NPCS', 300.00, 305.00, 'Girl',
180.00, '', 'VILLAGE_PEOPLE', 1, 'low', 'female', 'white',
'ss_001', 'evil01', 0.00, ACTIVE],}
That should be enough for now. As I explained above, you will find these lines as a comment at line
45ff. Just uncomment them to make them work. Do this now and then restart The Fall to visit your
first NPC.
You will find more information about NPCs in the chapter 'NPCs'.
Define a Function
We start by defining a new function for your dialog:
def tutorial_dlg_1():
Now is a good time to open the Application Programming Interface (API). It contains descriptions
and syntax for most functions defined in the engine and modules in the scripts directory. Open the
module dialog and read the examples. With this information build the following dialog:
def tutorial_dlg_1():
dialog.init_dialog(type=DIALOGSMALL)
dialog.add_text(text='Hi, do you have some meat?', speaker='NPC_1',
follower='ENDDIALOG')
dialog.start()
Look at the indentation: The three dialog lines are indented to mark them as a code block for
Python. In Python indentation is not only used for visibility but also to mark code blocks. In the
declaration of NPCs above it was only used for visibility, though. So just remember, indent every
code block and use additional indentations for visibility only for comments and lists/dictionaries
(everything in brackets).
For more information on dialogs visit chapter 'All Talk'.
Understanding Events
We still have one problem to solve: The engine needs to know when to start our function
tutorial_dlg_1(). All code in The Fall (at least all Python code) is called by events. Just think of it
this way: The player does something and the game reacts to that action. All events that the engine
can call are defined in object_events and system_events. All of these functions are also called in the
module of the actual zone mod_1.py. Some of them are in the basic zone script, but you can add
almost all other event functions to this module which are defined in object_events and
system_events (for exceptions, see chapter 'Events').
Using the Event on_approach()
Let’s use our problem as an example: 'When the player approaches the NPC, start function
tutorial_dlg_1()'. The program reacts to the action 'approach', so let’s search the API for something
close to on_approach(). This time the right event is not hard to find because its name fits its
function. However, it is not always that easy.
When you look at the module mod_1.mod_1 (mod_1.py in the same directory) you will find a lot of
events, some of them with basic code. The function on_approach() in there calls the
dialogs.on_approach(), so you just need to call your function in the dialogs.on_approach().
Def on_approach(target, operator):
# If talked to 'NPC_1' call dlg_1
if target == 'NPC_1':
tutorial_dlg_1()
You will find more information about the console and the command reload() in the chapter
'Debugging Python'. Just two things: The command reload() cannot add a new defined function.
You will always need to restart The Fall when you add a new function to a module. But do not
worry about that right now, I have placed all functions needed in this tutorial in the mod_1 module
so that you can play around with this command. Second, the command reload() is only a utility tool
and definitely has some bugs: Always make a full restart if you encounter 'unusual' behavior! But
still, the command saves more time than its problems should cost you.
Hunting
So she wants some meat. Could have been worse: Ever tried to find a rose in the desert? Just
creating some meat would be easy, but for a programmer the easy way is no fun and that is why we
will start with 'walking' meat.
Consulting the API turns up the following command:
system.create_animal(id, type, party, x, y, direction=180)
# inserting needed parameters makes it to
system.create_animal(id = 'ANIMAL_1', type = ANIMAL_WOLF,
party = 'ANIMALS', x = 315.00, y = 300.00, direction=180)
Attributes
Take a look at this code line:
objects.set_attribute(object = 'ANIMAL_1', attribute = 'foes',
value = ['UISPIELER'])
Attributes link data to an object. In the scripting layer of The Fall, objects are no real programming
objects but just addressed as data sets. The attribute system is the scripting equivalent to assigning
variables to a code object. Attributes are explained in detail in the API in the module attributes.
The attribute foes controls which characters an NPC would attack. UISPIELER (UIPLAYER) is the
group for all player controlled characters (PCs). Do not forget that the attribute foes needs a list [..],
even if only one enemy (or group) is set.
If you want to create an item on the ground it would be system.create_object, but right now we need
the above one.
Event Groups
Now the events for 'Use': I have already told you how to search for something with 'on_' and 'use'
and 'on_use' is one event that we will need. However, it is a little more complex now, because we
also need 'can_use'. Some events have an 'on_' and a 'can_' (and even some more) variation. The
'on_' event is triggered when the action is really executed and the 'can_' decides whether the player
can execute the action at the present moment.
First, allow AE to use the wolf:
def can_use( character_id, object_id ):
"""Returns True for items the character is able to use."""
if character_id == 'ALTER_EGO' and object_id == 'ANIMAL_1':
return True #allows action (on_use is started)
Now the code to create the meat. Again you should check which objects interact:
def on_use(character_id, object_id, item_id, item_type):
"""Is called when the player wants to use an item."""
if object_id == 'ANIMAL_1':
objects.create_item_in_inventory(character_id, 'SET_MEAT_RAW')
return True #stop here, because event is handled
Updating Code to Full PC Group
I used the variable character_id instead of the ID 'ALTER_EGO' and one might say that is a little
dirty, but it just left me another option: All PCs should be able do do most ingame actions, so let’s
change the can_use to:
def can_use( character_id, object_id ):
"""Returns True for items the character is able to use."""
if character_id in system.get_pcs() and object_id == 'ANIMAL_1':
#system.get_pcs() gives a list of all pcs
return True #tell engine to start on_use
So, enter, copy or uncomment the lines, reload the module mod_1 and try it.
The character should play through these animations one after the other, whereas code commands
would be executed in one frame (with no difference in game time). But try it, start this function
tutorial_mod.mod_1.mod_1.tutorial_animation() in the console. You will see the print right after
executing. Close the console and watch how the AE plays through these three animations one after
the other. But why?
Every object has a command stack for actions that take time. If one is finished, it will take a new
one from the stack, or execute a waiting animation. This works for commands like play_animation,
move_to, turn_to, pick_up and every other command that uses an animation.
Callbacks
You should ask yourself now: “But how do I execute new code after an action is finished?“ Look
up the play_animation command again in the API:
play_animation(char, animation, callback)
Yes, the parameter callback is able to call a function after the animation is done. But it needs a
pointer to that function: In Python a function called by function_1() is executed instantly and just
writing function_1 gives the pointer to that same function to be executed another time.
Try the following in the console:
objects.move_to_object('ALTER_EGO','NPC_1', callback =
tutorial_mod.mod_1.mod_1.play_dialog)
Now the dialog starts when the AE reaches the girl. Whereas the following command would start
the dialog and the movement at the same time:
objects.move_to_object('ALTER_EGO','NPC_1')
tutorial_mod.mod_1.play_dialog() # or dialogs.tutorial_dlg_1()
On your first try with callbacks you might get an error, because the engine tries to pass the object
ID as a parameter to the called function. That is why the function play_dialog holds a parameter:
def play_dialog(character_id = None):
dialogs.tutorial_dlg_1()
You cannot give specific parameters to be passed to your pointed to function, but the engine
automatically passes the object ID.
Lambda
I know this is hard to understand if you see time and code interacting for the first time, but still I
have to throw in another: Lambda and lambda.
First, forget the Python lambda, because it cannot be saved and would cause a lot of trouble if used
for zone scripting. You will find the Python lambda used in schedules, but they are not saved in the
savegame but uploaded from script and therefore compatible. Everywhere else you should use our
implemented function, the 'big' Lambda.
Lambda is a way to store a command with parameters for later execution. The pointer we used
above in the callback could not take parameters, but often enough you will need to pass additional
information.
lambda_string = "objects.move_to_object( 'ALTER_EGO', 'NPC_1') "
lambda_function = Lambda(lambda_string)
The function and parameters are passed as a string and stored in an executable code package that
fits in a variable.
Wanna see what executable code package means? Just enter the following lines into the console:
print_message = Lambda("print 'HELLO' ")
print_message()
And that is where the fun begins, but we are a mile too far for “First Steps.“ Do not worry, if you
cannot get callbacks and Lambda right in your first scripts, just copy and manipulate what you need
until it becomes clear. See you in the following chapters.
You can find the code in the functions callback_tests and callback_tests_dlg_2 at the end of module
mod_1.dialogs.
All modules marked with 'changeable' are parts of the main script module and are only used to
organize it in smaller and clearer chunks.
Events
All code in The Fall (at least all Python code) is called by events. Just think of it this way: The
player does something and the game reacts to that action. All events that the engine can call are
defined in object_events and system_events. All of these functions are also called in the module of
the actual zone mod_1.py. Some of them are in the basic zone script, but you can add almost all
other event functions to this module which are defined in object_events and system_events.
Exceptions to this rule are utility functions used by events defined in these modules. Check the API
or read the function to find out, whether it is an event or a utility function. If unsure, try the function
in the zone module and write a print in it.
Most events need to call the global function. Some only need to be executed. For others you have to
return their value ('return object_events.function()'). Look at these functions in the events modules
to find out how to connect local to global function. When your code solves the problem and you do
not need or want the global behavior, just finish the function with return:
def function_1(): # return a value or variable
if action == True:
return True
# the following code of this function would be ignored
# link to global event
return object_events.function_1()
− 'on_approach': To connect dialogs and schedule dialogs these events need the following local:
def on_approach(target,operator):
if not object_events.on_approach(target, operator):
dialogs.on_approach(target, operator)
# and in dialogs
def on_approach( target, operator ):
if schedules.Dialog(target, operator):
return
def on_wait_for_commando(id):
return schedules.Activity(id)
− 'can_examine_object': The local event 'on_examine' is only called, if the event returns True
(normally the local 'on_' event would be called, even if only the global 'can_' event was True).
Activating a Zone
Even if the zone is designed as a mod, the zone's name needs to be unique (like mod_1).
The position set here is not the same as in the layout manager, but the one the loading bar is
attached to (the travel points displayed while travelling).
Sky Color
Add the sky color of your new zone to the list in the module skies:
skies = {
"zone_1.zone_1": "yellow",
"zone_X.zone_X": "yellow",
# or
'new_mod.mod_X.mod_X' 'yellow',
Resting Place
The resting place is defined in the module rest:
def init_data():
if not hasattr(data("rest"), "legal_rest_areas"):
data("rest").legal_rest_areas = {
"zone_1": [ ( 566.57, 504.53 ) ],
'zone_X' : [(500,400)],
# or
'mod_X': [(500,400)],
Activating Respawn of Animals
Dead animals will only be replaced if allowed in the module spawnanimals. Make sure that animals
in your zone use the usual data structure:
SPAWN_ANIMAL_ZONES = [
'zone_1.zone_1',
'zone_X.zone_X',
# or
'new_mod.mod_X.mod_X',
To use the new map as the starting map for the campaign set in global_defines:
ENTRY_ZONE = "zones\\zone_X\\zone_X"
# or
ENTRY_ZONE = "new_mod\\mod_X\\mod_X"
NPCs: 'A New Star is Born'
Every character in a game is an NPC (None Player Character). Even PCs (Player Characters) are
only NPCs whose control is transferred to the player. The few differences between these two types
will be pointed out in the last section.
Animals are not that different from NPCs; just look up their types in the basic npc.py.
Basic Creation
Take a look at the npc.py of the empty or tutorial zone:
def init_npcs():
for npc in npcs.keys():
system.create_character(
id = npc,
gender = npcs[npc][0],
party = npcs[npc][1],
x = npcs[npc][2],
y = npcs[npc][3],
name = npcs[npc][4],
direction = npcs[npc][5],
resourceui = npcs[npc][6])
objects.set_attributes(npc,
faction = npcs[npc][7],
level = npcs[npc][8],
model = npcs[npc][9],
gender = npcs[npc][10],
skin = npcs[npc][11],
clothes = npcs[npc][12],
face = npcs[npc][13])
character.update_appearance(npc)
if not npcs[npc][14] == 0.00:
character.scale(npc, npcs[npc][14])
objects.set_active_state(npc, npcs[npc][15])
It uses the dictionary npcs to create a character and set all necessary attributes. The variables are:
− 'id': The ID of the new NPC; must be unique.
− 'gender': Male or female; can be changed later.
− 'party': Sets the party; see below.
− 'x,y': Position.
− 'name': A string is a variable of the module globaltext holding a localized name; can be changed
later.
− 'direction': Initial direction the character faces.
− 'resourceui': Empty string or name of picture for large dialogs; can be changed later.
− 'faction': Used for setting HP and XP.
− 'level': The level; used for calculating skills and attributes.
− 'model': Low for NPCs, high for PCs and child for children; controls model complexity.
− 'skin': Color of skin: black, white, red, grey.
− 'clothes': Sets the body texture for low and child models; directory textures\\characters\\human.
− 'face': ID of the face.
Party
Every NPC needs to be part of a party. Three main parties are always defined, but you can create
additional ones for different NPC groups in a zone:
system.create_party(id="NPCS",type=PT_COMPUTER)
system.create_party(id="UISPIELER",type=PT_HUMAN)
system.create_party(id="ANIMALS",type=PT_COMPUTER)
Clothes
All character textures are placed in the directory textures\\characters\\human, and in the file
scripts\\character_py.py you will find how to address them.
"ll_001": ("ll", "body",
baseres+"low\\male\\ll\\low_body_ll_001_%(skin)s.png")
Faces
Same directory as clothes and again the scripts\\character_py.py translates ID into file.
"evil01": baseres+"low\\faces\\female_low_face_evil01.png"
Active
Like all objects NPCs can be turned on or off with:
objects.set_active_state( ID, True )# or False
Immortal
To keep quests active some NPCs need to be immortal (they cannot be attacked, wounded or
killed).
objects.set_immortal_state( ID, True)# or False
Approachable
NPCs are by default approachable (the player can speak to them) and show this on mouse over
(dialog icon). Deactivate this attribute if the NPC has no dialog at the moment or no dialog at all
(combat NPCs).
character.set_approachable_state( ID, True) # or False
Daily_routine commands
See chapter 'Daily Schedule' for more information on this.
Foes
The attribute foes controls what kind of characters an NPC will attack. It holds a list of IDs or
parties (e.g.: UISPIELER).
objects.set_attribute( ID, 'foes', ['UISPIELER'] )
Scale
The scale of characters can be changed, but stay within the usual frame, because animations and
objects only fit for normal scale NPCs.
character.scale(ID, height )
Equipping NPCs
Items
NPCs only need items as loot or for special animations (e.g.: chopping wood). During an active
schedule the objects needed are generally created and removed afterwards. Here some commands to
create, equip and remove items:
objects.create_item_in_inventory( ID, ITEM_TYPE)
character.equip( ID, ITEM_ID) # or ITEM_TYPE
character.equip_direct( ID, ITEM_ID) # doesn't play animation
character.un_equip( ID, ITEM_ID)# or ITEM_TYPE
objects.remove_item_from_inventory( ID, ITEM_ID)#or ITEM_TYPE
Weapons
NPCs do not need ammunition. They will always load empty weapons back to a full clip.
An unarmed NPC will equip himself with a weapon found in his inventory when he starts an attack.
The fastest way to arm an NPC is:
character:equip_direct( ID, ITEM_TYPE,
creation=True, # Create a new weapon
direct_ammo_load=Ture )# load it without animation
Voice_id
The attribute voice_id is used to select the speech sample for a mercenary. The ID is the voice ID
plus the text ID (e.g: mercenary_carmen_examine_item_found_1.ogg).
This also switches AE speech: Leave blank for male AE and set to 'AEF' for female.
ID Card
The attribute passport = True activates the ID card for PCs.
All Talk: Scripting Dialogs
The Fall uses two main dialog types:
Small Dialog
Small dialogs appear in a box above the speaker’s head and the game continues while playing this
dialog. Long small dialogs should be played in cutscenes, because you can never know when the
player moves away from the speaker. The game can play multiple small dialogs but most times it is
better to allow only one at a time.
Large Dialog
A large dialog opens a dialog box consisting of a picture of the actual speaker and a text field. The
game pauses while a large dialog is active and it may contain choices. All active small dialogs are
cancelled when a large dialog starts, and of course only one large dialog can be active.
I will start the following sections by explaining how to set up the text in localizable IDs. Probably
you will not localize a mod, but working with text IDs will be easier in complex dialogs.
After that I will show you the basic structure of branching (choices) dialogs and multiple entry
points.
The third section will point out some tricks to force-fit complex dialogs into our code structure, and
the last section explains how to remember spoken parts.
All texts are initialized in modules named after their language (e.g: english). These modules exist
for every zone (like zone_1.zonetext.english) and there is also one for global texts
(globaltext.english.english). A normal text entry for a zone would be:
## Dialog 001: The player approaches the president’s house unauthorized
add_zone_text( id='D_001_T_001',
text="""Stop! That's close enough. Now beat it! """,
speaker="""Wache_1_Z1""",
audiofile="",
comment=""""""
)
The text entry contains the ID of this dialog and the text string. The other parameters speaker,
audiofile and comment are not used in the game and are only for creating the speech files.
All IDs are in capital letters for script use but the file names for speech are in lower case.
The text strings are marked with three “ to allow most sign combinations in the text.
Global texts are nearly identical, but use the command add_global_text instead.
Dialog Choices and Branches
Besides the command dialog.add_text() described in the chapter 'Her First Words', large dialogs
contain choices and are non-linear. Take a look at dialog.add_choice() in the API:
dialog.add_choice(text, follower, callback=None, order=0,
auto_deactivation='normal')
A set of dialog choices needs to be declared successively and the IDs need to be of the form:
'D_xxx_C_yyy_z' (x = dialog nr., y = choice set nr., z choice nr.). Dialog choices are normally
listed in order of appearance, but they are changeable with the parameter order.
In general, the dialog texts are played in the order they are coded, but this can be changed with the
parameter follower. This parameter is needed in an add_choice and useful in add_text to build
complex dialog.
dialog.add_choice('D_001_C_001_1', follower = 'D_001_T_001')
dialog.add_choice('D_001_C_001_2', follower = 'D_001_T_003')
dialog.add_choice('D_001_C_001_3', follower = 'ENDDIALOG')
dialog.add_text('D_001_T_001', 'NPC_1')
dialog.add_text('D_001_T_002', 'ALTER_EGO', follower = 'D_001_C_001')
dialog.add_text('D_001_T_003', 'NPC_1', follower = 'D_001_C_001')
Line 'D_001_T_002' follows line 'D_001_T_001' in code and dialog so the parameter follower is
not needed here. The follower 'D_001_C_001' sends the dialog back to the choice set.
Next, we want choice two to be only available after choice one is played. Dialog lines can be added
after a dialog is finished and started:
dialog.add_choice('D_001_C_001_1', follower = 'D_001_T_001',
auto_deactivation = 'permanent',
callback = Lambda("dialog.add_choice('D_001_C_001_2',
follower = 'D_001_T_003')"))
dialog.add_choice('D_001_C_001_3', follower = 'ENDDIALOG')
Through restart of a dialog you can build any form of dialog structure, but a dialog designed to
work without this trick is always better.
The command jump_to can also be used in a callback to override the follower.
Daily Schedule: 'Everyone Has to Make a Living'
Everyday behavior of NPCs is defined in their schedule. A schedule is a dictionary of persons,
times and actions. The modules daily_routines and npc_activities hold all code and utility functions
to make the schedules work. Additional local functions and the schedules for all NPCs in a zone are
defined in the module schedules of the current zone.
You will now learn how a schedule is structured, how to deactivate or pass the schedule and some
basic schedule sets.
ID of NPC
The first layer is a dictionary with the ID of the NPC. The value is either a list of schedules or a
single schedule (go to third layer: dictionary of timeframes).
List of Schedules
If a list of schedules is found, the first schedule in which the function marked by the keyword
S_CONDITION is True is used. If no keyword S_CONDITION is defined, it is considered as True.
The keyword S_CONDITION can be found in the third layer dictionary (see below).
Dictionary of Timeframes
The third layer uses the starting time of timeframes as dictionary keywords. Also, the keyword
S_CONDITION can define a condition for this schedule in this level. A second keyword accepted
here is S_SECONDARY_DIALOG. This may contain a dialog ID or a function playing a dialog. The
secondary dialog is used when the dialog defined for a timeframe was already played or is not
defined.
Dictionary in a Timeframe
This dictionary can accept a number of keywords:
S_START: Functions executed at the start of this timeframe.
S_LOOP: Functions executed again and again in this timeframe (after S_START).
S_DIALOG: A dialog ID or function/code object playing a dialog. NPC ID is passed to the function.
S_LOCATION: Defines a number for this timeframe.
S_NOSTOP: List of location (frame) numbers; omit S_START for listed numbers.
List of Functions
All elements in this list need to be executable code objects (Lambda or lambda). The module
npc_activities holds a lot of functions returning the right code objects for this purpose.
"14:00:00":{S_START:[npc_activities.goto(300,300)]},
# this function returns and inserts
"14:00:00":{S_START:[lambda char: objects.move_to(char, 300, 300)]}
'allow/prohibit activity'
Getting a new schedule action can be switched on and off with the commands
daily_routine.allow_activity() and daily_routine.prohibit_activity(). When issuing commands to an
NPC (e.g. for a cutscene) you should switch off schedules during these commands or get most
unusual results.
Using Schedules
Basic Timeframe
In a basic timeframe an NPC moves to a new position, maybe executes a starting animation (both in
S_START) and then a loop animation until the time is up. The timeframe is switched to the next
frame and in between the npc_activities.finish_activity issues finishing animations if needed.
"14:00:00":{S_START:[npc_activities.goto(300,300),
npc_activities.start_chop_wood()],
S_LOOP:[npc_activities.chop_wood()]}
#there is no finish_chop_wood because this animation is issued
automatically when finishing a timeframe
Continue Loops
One never knows at what time a schedule for an NPC will start. The time can even jump, by
revisiting a zone or taking a rest. Therefore, every timeframe should have the keyword S_START to
make sure that the NPC moves to the right position. Take a look at this:
"14:00:00":{S_START:[goto_object('bench_1'),
sit_down_on_bench()],
S_LOOP:[sit_on_bench()]},
"14:30:00":{S_START:[goto_object('bench_1'),
sit_down_on_bench()],
S_LOOP:[read_book_on_bench()]}
Using this schedule would make the NPC stand up at 14:30 and then sit down again on the bench. It
would be better to have the NPC sitting on the bench uninterrupted. He should only take out a book
to read.
That is what the keyword S_NOSTOP does:
"14:00:00":{S_START:[goto_object('bench_1'),
sit_down_on_bench()],
S_LOOP:[sit_on_bench()],
S_LOCATION:1},
"14:30:00":{S_START:[goto_object('bench_1'),
sit_down_on_bench()],
S_LOOP:[read_book_on_bench()],
S_NOSTOP:[1]}
In the first frame a location number is set and the second frame omits the functions defined in
S_START when the previous timeframe had the number [1].
However, the character still needs to be moved to the starting position before using the animating
functions.
Gender-specific Dialogs
The command npc_activities.gender_switch() can be used to allocate different dialogs for gender:
S_DIALOG :gender_switch('NPC_MARIA_T_005F', 'NPC_MARIA_T_005')
Long Dialogs
Sometimes it is necessary to play more than one dialog line in a timeframe or the AE needs to
comment on an NPC. Therefore the command npc_activities.longdialog() can be used in the
schedule to play through a list of dialog lines:
S_DIALOG :(long_dialog([['ALTER_EGO', 'D_186_T_001']]))
S_DIALOG :(long_dialog([['ALTER_EGO', 'D_001_T_001'],['NPC_1',
'D_001_T_002']]))
Specials
Effect Dummy
If your item is going to be a firearm, it needs an effect dummy, that is a node defining position and
direction for graphic effects. The dummy 'Dummy_muzzleflash' is reserved for the fire effect at a
weapon's muzzle. This dummy node is needed and must be linked to the mesh node for the
equipable object.
You can define additional dummy nodes for your own scripting. And even some world objects have
dummies. They are used to position NPCs for interaction with this object (bench, houses).
However, there should be enough examples of scripted objects in The Fall’s code.
Scripting
'objectdata\items'
The first data set goes into 'maindirectory'\scripts\objectdata\items.py.
# create a new data set
add_3d_item_data(typeid='RES3D_ITEMX')
# the two mesh nodes: first for ground item, second for hand item
objects.set_attribute(object='RES3D_ITEMX', attribute="states",
value=['ITEMX_00','ITEMX_01'])
# unequipable items only need one mesh node for ground
The offset parameter defaults to zero for all possible models (male_low, male_high, female_low,
female_high, child_low) and is not needed. Every entry needs the following elements:
− Model type (male, female, child)
− Model complexity (high, low)
− Connected node (node_pistol, node_rifle)
− Adjustment vector (x,y,z) in centimeters
'itemdata'
Three files define items: weapons.py, items.py, ammo.py. These files are in:
'maindirectory'\scripts\itemdata.
The parameters for all item types are:
# create the data set: create_weapon_type, create_ammo_type,
create_item_type
create_weapon_type(typeid='SET_ITEMX')
# Component list
"combination_list": [['SET_HK_USP_45','SET_SILENCER']]}
Ammo parameters:
# Area of effect; shotguns, explosives
objects.set_attribute(object='SET_AMMOPACK_7_65_MM',
attribute="wirkungsbereich", value=0.00)
# Damage range
objects.set_attribute(object='SET_AMMOPACK_7_65_MM',
attribute="schaden_organisch_min", value=1)
objects.set_attribute(object='SET_AMMOPACK_7_65_MM',
attribute="schaden_organisch_max", value=2)
# Rounds per pack
objects.set_attribute(object='SET_AMMOPACK_7_65_MM',
attribute="schuss", value=30)
# ballistic curve
objects.set_attribute(object='SET_AMMOPACK_7_65_MM',
attribute="schussbahn", value=LINEAR)
Weapon Events
Just a list of possible events to link special functions for a weapon:
− object_events.on_(un)equip: When item changes something while being equipped.
− object_events.get_hit_chance_factor: The weapon might perform better while being in a prone
position.
− object_events.get_damage_factor: Your weapon might use an ammo type that is more effective.
− weapon_events.on_weapon_fire_single(multi): Add more than a flash when firing your weapon.
The Structure
Mods are placed in the directory mods in the The Fall’s main directory. All directories placed in
there need to be Python packages. That means they need a file named '__init__.py'. This file is
usually empty, but its existence tells Python to treat this directory as a package.
In addition to that the mod package needs the file startup.py. This file contains the initialization and
is covered in the next chapter.
Also there should be a directory named 'overwrite'. Every file placed in this directory will replace
its equivalent game file. You need to recreate the game directory structure to add the files to the
program structure at the right place.
Besides this, you can place additional files, modules and scripts in this directory to use in your mod.
Now take a look at the tutorial mod:
In the mod’s directory is the base directory (package)
tutorial_mod of the tutorial mod.
This directory contains the files __init__.py and startup.py and the
directories overwrite and mod_1.
The directory mod_1 is a full zone package and the directory
overwrite holds the files needed to integrate a new icon for the
travel map. The directory structure is a copy of the game directory
structure but only holds the necessary files.
Remember, every file in the main directory of your mod is used only when your scripts address it.
And everything in the overwrite directory replaces existing game files, so be careful what to place
in there, because only one mod at a time can replace a specific file.
Problems could arise with replaced script files. Replacing script files can be avoided by a clever use
of the module startup (see below).
'tutorial_mod.mod_1.mod_1'
# internal identifier for data(), and most lists
data('tutorial_mod.mod_1.mod_1').variable = True
The path for files placed in the mod directory also starts with this directory:
# adds coordinates for the travel map
system.zones_list['mod_1'] = ("tutorial_mod\\mod_1\\mod_1",
[505.00, 477.00])
But remember that files placed in the overwrite directory are accessed as if they were in the original
game directory. You could now use the overwrite function to integrate every mod file into the game
directory structure, but that would make it more difficult to distinguish between mod and game
files. So use overwrite only for replaced files and place new files outside the overwrite directory.
system.function = function
# Function without brackets gives the pointer to that function
Now we use this to insert our new commands for an event in the global event:
# global variable for pointer to global event
global_event = None
def example_event():
# inserted code
example_code()
def mod_init():
# remember pointer to global event
global global_event
global_event = object_events.example_event
And this is the right way to do it. Do not change the global function or overwrite it entirely! Always
call the original global event, because that way the original code and other mods can work together
with your mod (as long as the code you insert is compatible).
If you really need to pass existing global script, then make sure that you only omit the global call
for those event calls that would not work together.
Or call your new global event only in your zone. Let’s say you created a new zone and this zone
cannot work together with the global on_object_killed. The local event is always called first (if it
exists) and has to call the global event. Now insert a call to your global event instead of the call to
the original global event. That way all other zones can still use the original global script, because it
is not changed.