# Public Scripts 2.0

### Tom N Harris

`<telliamed@whoopdedo.org>`

## Introduction

The Public Scripts package is a collection of scripts modules for Dark Engine™ based games. These modules collect a number of well-known scripts into a single place. So fan-mission designers have greater freedom to create novel and entertaining experiences.

This manual is divided into three parts.

Installation: | If you just need Public Scripts in order to play a fan-mission, this is the only section you need to read.
DromEd Reference: | Designers will find descriptions of the scripts here; and instructions on how to use them.
Programmer’s Reference: | This section describes the source code to Public Scripts for anyone who wants to make their own custom scripts.

## License Agreement

Public Scripts are copyright © 2005-2007 Tom N Harris.

This software is released under the terms of the GNU General Public License.

Unmodified copies of the compiled binary files may be distributed along with fan-missions and expansion packs intended for use with Dark Engine™ based games without the creator being required to provide the source code for this software. The fan-mission or expansion pack must completely comply with the terms of the Dromed License issued by Eidos Interactive, and the fan-mission or expansion pack must include the following copyright information:

> This fan-mission uses Public Scripts. Copyright © 2007 Tom N Harris This software is licensed under terms of the GNU General Public License. Please see http://www.thiefmissions.com/telliamed/#PublicScripts for more information, or write to [insert your email address here].

You must then be prepared to answer any queries regarding the scripts, which may include offering copies of the original software package in case the official website is inaccessible.

Third-party distributors must include the complete Public Scripts package in their archive if they distribute any fan-missions or expansion packs that use this software.

## Chapter 1. Installation

## Installing Public Scripts

The first step to using a custom script module is to copy the appropriate files to a place where the game can find them. The Public Scripts package uses three files: script.osm, version.osm, and dh2.osl. But the first file, script.osm must match the game it is being installed for. A script module from Thief Gold can’t be used in System Shock 2. (Although there are exceptions, like version.osm.)

The simplest way to copy the right files is to run the included Setup.exe program. This is an automated installer that will copy the right files to the right places. If you already have a copy of Public Scripts installed, the older files will be backed-up to a zip-format archive with a name like _Restore-20060201.zip, although the numbers will be different. If there is a problem, you can restore the old files from the backup archive.

## “Gaylesaver” Scripts

The main Public Scripts script module is named script.osm. This is the same name as an older script module distributed as “Gaylesaver’s Custom Scripts”. The reason the names are the same is because Public Scripts includes scripts that do the same thing as the “Gaylesaver” scripts. These are not merely copies, but completely new scripts made to be compatible, but with less problems than the originals. The “Gaylesaver” scripts are no longer being updated, so I am providing Public Scripts as an improved alternative.

You cannot have both Public Scripts and the “Gaylesaver” scripts installed at the same time. When you install Public Scripts, the old script.osm will be overwritten. The old file darkhooks.dlx is not removed, however. This is harmless, but if you have no intention of ever using the “Gaylesaver” scripts again, then you probably want to delete it.

# DromEd Reference

This section is for fan-mission authors.

## Chapter 1. VersionCheck

You are free to include copies of script.osm and dh2.osl with your fan-mission, provided that you follow all the rules. But do you really want to? Scripts are computer code, and some people may rightfully be concerned about letting any random computer program they download be run on their computer. There is also the possibility that there may be a bug in this particular version of Public Scripts. (And a very good possibility at that, it annoys me to say.) So do you really want to have to release a new copy of your FM every time I discover some new problem with the scripts; or worse, leave an old buggy copy floating around?

The more reasonable solution is to ask the end-users to download the scripts themselves. They can be more confident that the scripts are safe, and upgrade whenever the need arises. To make this practical, though, you need a way to notify the user when the scripts have not been installed. The script VersionCheck is what makes this possible. This script is placed into a separate module named version.osm, and it is this file that you include with your FM. The same file can be used in Thief 1, Thief 2, and System Shock 2.

The VersionCheck script is intended to be used as a trigger. If the required scripts are found, it will send a TurnOn, or it will send TurnOff otherwise. Specify the script modules to look for in the Editor\Design Note or, in System Shock 2, Script\Objlist. The property is a list of file names separated with semi-colons (`;`). If a file doesn’t have an extension, then .osm will be added. The script will fail if any of the files can’t be found in the game directory. The version of a file can be checked by typing a ‘`=`’ followed by the minimum version number. The script will fail if the version of the file is lower than specified. The following example tests if script.osm is present, and if tnhscript.osm is at least version 1.5.

`script.osm;tnhscript=1.5`

VersionCheck can also display a message if the scripts aren’t found. In Thief, it uses the Book\Text and Book\Art properties. It’s just like any other book. In System Shock 2, the property Script\Use Message is used. The property value is the name of a string that will be read from the file strings\error.str.

## Chapter 2. Dark Hook 2

Some of the scripts need an external library called Dark Hook 2. This is provided by the file dh2.osl. If the file isn’t found then the script won’t operate. However, other scripts that don’t require Dark Hook 2 will still work.

## Chapter 3. Overview

## Using the Scripts

Before using any scripts, you must load the appropriate modules into each mission. You’re probably already familiar with doing this for gen.osm, convict.osm, or allobjs.osm. A custom script is just one more module that needs to be loaded. DromEd lets you load as many script modules as you want.

Type the DromEd command: script_load and the name of a script module to load it. The .osm extension isn’t necessary. When DromEd needs a script, it will search each loaded module beginning with the most recently loaded. You can print the list of loaded modules to the monolog with the command script_dump_files.

Scripts are attached to an object with the Scripts property. You can put the names of four scripts in each property, but DromEd will combine all the Scripts properties from all of the ancestors of an object. This is different than other properties where each object will override the properties that come before it. When you need to override an inherited script property, you set the Don’t Inherit flag on the Scripts property.

Scripts also inherit features of base scripts, so many scripts can have similar behaviors. This inheritance is built-in to the scripts and doesn’t require you to do anything in DromEd. The inheritance described in this manual refers to this, not the object hierarchy. Some of the base scripts are also described separately, to make the manual easier to read.

## Debugging Scripts

The more you use scripts, the more you need to know about what is going on behind the scenes. This becomes most obvious when the game isn’t working as you expected it to. DromEd provides some commands to aid in the debugging of scripts. To view the debug information, you need to have a monolog enabled. The monolog is a text file that records messages from the DromEd, the game, and some scripts.

There are two ways to enable a monolog. You could tell DromEd to automatically open it at startup. Edit your dromed.cfg or user.cfg configuration file. (I prefer to use dromed.cfg for editor-only options.) Add on a new line the option monolog and the name of the file you want to create. The disadvantage with automatically opening the monolog is that the previous contents of the file will be erased each time you start DromEd. Instead, you can manually open the monolog every time you need it. After starting DromEd, type the command mlog and the name of the file. If you type mlog close, then the monolog is closed. Opening a monolog with a different name will close the previous file.

With the monolog open, you can use DromEd’s built-in script debugging commands. These are called trace lines. A trace monitors the messages sent to a particular object. You create a trace with the trace_add command. The command takes four arguments, the object to monitor, the message to trace, the word “`spew`”, then a trace line number. A trace line is a group of traces so you can toggle many traces on and off together. There are 32 trace lines. A line is toggled with the trace_line command. The “`spew`” argument tells DromEd to write the message to the monolog. The word “`break`” could also be used, but this is only useful for script programmers with a symbolic debugger installed.

Trace lines just tell you when an object receives a certain message. Many messages contain extra information that you may want to know about. Public Scripts includes a script for this purpose. Add the script Spy to any object and it’ll record every message that the object receives in the monolog, along with the extra information from the message.

## Design Note Parameters

Many custom scripts need extra information to function. They may use an already existing property, but most often there isn’t anything suitable. So a special string property is used to give options to the scripts. In Thief this is the Editor\Design Note, and in System Shock 2 it is the Script\Objlist. This will be referred to as the “design note” from now on.

The design note consists of a list of parameter names and values separated with semi-colons (‘`;`’). Parameter names do not contain spaces and are not case-sensitive. The parameter name is followed by ‘`=`’ then the value. Any space before or after the value will be ignored. The value can be enclosed in single or double-quote marks, which must be done if you need to use a quote mark or semi-colon in the value. The value may be interpreted as an integer, floating-point number, string, boolean, time, or object.

Integer: | A whole number, positive or negative.
Floating-Point: | A positive or negative number with optional fractional part. Use a period (‘`.`’) to separate the whole and fractional parts.
String: | Any kind of text.
Boolean: | A true or false value. The words ‘`true`’ or ‘`yes`’, or a non-zero number will be considered true. You can also shorten the word to a single letter, i.e. ‘`T`’ for true and ‘`F`’ for false.
Time: | As a number by itself, it’s milliseconds. Put the letter ‘`s`’ after the number for seconds, and ‘`m`’ for minutes.
Object: | A DromEd object. Can be the numeric ID, or the name of the object.
Color: | Color values can be written in HTML format, which is a hash mark (‘`#`’) followed by six hexadecimal numbers. The English color names described in HTML 4 are also recognized. Another way to specify a color is the red, blue, and green components (in that order) separated with commas.

Where an integer, boolean, or time is requested, you can substitute the name of a quest variable for the value. Type a dollar sign (‘`$`’) followed by the name of the qvar.

## Common Trap Features

Many of the scripts are types of “traps”. (The terms “relay”, “router”, “filter”, and “trigger” are also sometimes used, but they all amount to the same thing.) The purpose of a trap is to respond to, or generate, TurnOn and TurnOff messages. Some traps both respond to and generate messages. And sometimes one or the other message will be ignored.

Traps are usually linked together using ControlDevice links. System Shock 2 uses SwitchLink links instead, but this manual will only refer to ControlDevice; you’ll just have to mentally translate for SS2.

The behavior of a trap can be altered with the Script\Trap Control Flags property. The Invert flag will reverse the normal meanings of TurnOn and TurnOff. Once causes the trap to be locked after it has been activated. The NoOn and NoOff flags make the trap ignore the respective messages. (Prior to reversing by Invert.) In System Shock 2, Enter means NoOff and Exit means NoOn.

Thief 1 doesn’t have the Script\Trap Control Flags, so a design note parameter is used instead. The parameter name is tcf and it is specified as a string of two-character symbols. The flags are:

`!+`: | `NoOn`
`!-`: | `NoOff`
`<>`: | `Invert`
`01`: | `Once`

When a trap is locked, it will ignore all messages. A trap that has been turned on will automatically turn off if the Script\Timing (Thief) or Script\Delay Time (SS2) is set. The time is in milliseconds for Thief and seconds (with fractional part) for SS2. The timer is not used when a trap is turned off.

In the Thief games, it is possible to link to the Player object. Create the link to the starting-point marker and when the game starts, those links will be moved to the Player marker. This even applies to some non-trap scripts.

## Chapter 4. The Scripts

## Script Summary

Compatible Scripts: | These are scripts that appeared in an older custom script module.
Common Scripts: | These scripts are useful in all games.
Thief 1 Scripts: | Scripts for Thief: The Dark Project and Thief Gold.
Thief 2 Scripts: | Scripts for Thief 2: The Metal Age.
SS2 Scripts: | Scripts for System Shock 2.

## Compatible Scripts

These are scripts that appeared in an older custom script module. Missions that already use the older version should be able to upgrade simply by changing the OSM file.

## AIItemGiver

Allows an AI to transfer an item from it’s inventory to another object.

Script: | AIItemGiver
Inherits: | BaseScript
Messages: | TransferItem
Links: | Contains

This script is intended to be used from a pseudo-script; usually a conversation. Place the script on an AI in the conversation that Contains some object. Use the Script message command to send the message TransferItem to the actor. The other two arguments are the destination (MsgData1) and the object to transfer (MsgData2). The item will then be removed from the AI’s inventory and put in the inventory of the destination. Objects that combine, even loot, will transfer properly.

## Forwarder

Relays specific messages to other objects.

Script: | Forwarder
Inherits: | BaseTrap
Links: | ScriptParams(message)

This is a generic relay and filter that works with any message. Instead of the usual ControlDevice or SwitchLink links, it uses ScriptParams where the data of the link is the name of the message that will be relayed. You can have any number of links with different data. The length of the ScriptParams data field is only 15 characters, though. You can get around this redirecting the script to read the message name from an object property. For the link data, type the character ‘`#`’ then the name or ID of an object. On that object, add a design note and set it to the name of the message to be relayed. The entire design note will be read, so you can’t be using it for any other parameter.

## IntrinsicCover

Display text when focused.

Script: | IntrinsicCover
Inherits: | IntrinsicText
Messages: | WorldFocus

A variation of IntrinsicText that displays the text when it receives WorldFocus.

## IntrinsicPlaque

Display text when frobbed.

Script: | IntrinsicPlaque
Inherits: | IntrinsicText
Messages: | FrobWorldEnd

A variation of IntrinsicText that displays the text when it receives FrobWorldEnd.

## IntrinsicText

Display colored text.

Script: | IntrinsicText
Inherits: | BaseTrap
Parameters: | text(string), clr(color), clr_red(integer), clr_green(integer), clr_blue(integer), time(time)
Properties: | Book\Text

IntrinsicText displays text on-screen when triggered. If the Book\Text property exists, then it is used as the name of a string file to read. Without a book file, the text to display can be written in the design note. Using a book allows you to display translatable text; but the design note doesn’t require you to create a custom resource.

When reading the text from the design note, the text parameter will be used if it exists. Otherwise, the entire design note is shown. You must use text if you want other parameters.

The clr parameter will change the color of the text in Thief. Alternately, the three parameters clr_red, clr_green, and clr_blue can be used. On-screen text color can’t be changed in System Shock 2. The length of time the text is shown is determined by the number of words. You can specify an duration with the time parameter. The time and clr parameters can be used with either Book\Text or the text parameter.

## InvSchema

Play a schema when frobbed.

Script: | InvSchema
Inherits: | BaseScript
Messages: | FrobInvEnd
Links: | SoundDescription
Properties: | Sound\Object Sound

When the object is frobbed in the inventory, a specified schema will be played. If the frobber is the Player, the schema will be played as an ambient, otherwise it is played normally at the location of the frobber.

Thief: Create a SoundDescription link to the schema. The link can be from an archetype of the script object as well.

SS2: Set the schema name in the Sound\Object Sound property.

## LinkTemplate

Move links from one object to another, including data.

Script: | LinkTemplate
Inherits: | BaseTrap
Parameters: | object(object), dest(object), flavor(string), on_create(boolean), off_destroy(boolean), singleton(boolean)

This trap will add links to another object when turned on, and remove them when turned off. It is a template because the links are originally created anchored to the script object. That way, the link data can be set appropriately.

The object parameter is required and specifies the object that will become the new source of the links. If dest is specified, then only links to that object will be moved. Flavor will only move those types of links. If it isn’t specified, then all links except reverse trigger links will be moved.

On TurnOn, a copy of each valid link will be created with the object object in place of the script object. The link that was on the script object will then be deleted. If on_create is set, then the old links are not removed. On TurnOff, valid links with object as the endpoint will be removed, and re-linked to the script object. If off_destroy is set, then the links are not re-linked. Note that it’s possible that the links removed from object could be different than the ones originally copied to it. For instance, if you just add one Contains link on TurnOn, then TurnOff will move all the Contains links including those not added by LinkTemplate. Using a specific dest will usually avoid unexpected side-effects.

Some links, such as AIAwareness, only work right if there is just one link between any two objects. Otherwise you’ll get an error that says “`Singleton link expected`”. You can instruct LinkTemplate to avoid duplicate links by setting the singleton flag.

## PhysModelCorrect

Adjust the object’s physics to match its true size.

Script: | PhysModelCorrect
Inherits: | BaseScript
Messages: | Sim, PMResize
Properties: | Physics\Model\Dimensions, Shape\Scale

Normally, resizing an object in DromEd does not alter the physical size of the object. You could manually adjust each resized object, or you could save time and just add this script. When the game starts, this script evaluates the Shape\Scale of the object and its archetype to determine the true size of the object. The Physics\Model\Dimensions property is then set accordingly. This works for Sphere and SphereHat objects as well as OBBs.

The dimensions can be readjusted at any time by sending PMResize to the object.

## RandomRelay

Trigger a randomly selected object.

Script: | RandomRelay
Inherits: | BaseTrap
Links: | ControlDevice, SwitchLink, ScriptParams(weight)
Parameters: | reusable(boolean), rechargeable(boolean), preserve(boolean), weighted(boolean)

A RandomRelay relays a TurnOn or TurnOff message to a randomly selected destination. The simplest mode is un-weighted and uses standard trigger links. After the relay has been used, it will lock itself. Essentially, this trap has the Once trap control flag on by default. You must set reusable to use the relay more than once. But each destination will only be triggered once, and the link to the destination removed. To keep the links intact, set preserve.

RandomRelay can also work with weighted destinations. Destinations with higher weights, relative to the other destinations, are more likely to be chosen. The destinations are linked to with ScriptParams and the data of the links are set to the weight for that destination. Reusable and preserve also apply to weighted relays. Additionally, the relay can be rechargeable, which implies preserve. A rechargeable relay will disable a destination after it is used, but maintains the link. When all links have been used, the relay is reset and it can send to previous destinations again.

This script is also named RandomRelay1x2. There is no difference.

## Sippable

An object that can be used a fixed number of times.

Script: | Sippable
Inherits: | BaseScript
Messages: | FrobInvEnd, Contained
Properties: | Inventory\Object Name, Obj\Object name
Parameters: | sips(integer)

A Sippable object display a usage count as part of its inventory name. When it is frobbed in the inventory, the count is reduced by one and, if there are no more uses left, the object is destroyed. The inventory name of the object is set as usual, in the Inventory\Object Name or Obj\Object name property. In the string resource, include the sub-string “`%d`” in the name. That sub-string will be replaced with the number of uses.

`Magic Potion\n %d sips left`

If the string resource doesn’t exist, or there is no “`%d`” in the name, then a fallback, but untranslatable, method is used. The number of uses plus the words “`sips left`” will be added to the end of the object name.

## Spy

Display all messages received by the object.

Script: | Spy

This is a debugging aid. It shows every message that is received by an object. The messages are shown on-screen as well as coped to the monolog. Much of the additional data that accompanies messages is also displayed. Using Spy can help you make sense of the complex interactions of objects. Or it’ll just confuse you way more than you already are.

## TimedStimulator

Periodically stimulate linked objects.

Script: | TimedStimulator
Inherits: | TrapStim
Links: | ScriptParams(interval)
Parameters: | interval(time), stage(integer), device(boolean)

...

## ToolMP

...

Script: | ToolMP
Inherits: | BaseScript
Messages: | FrobToolEnd
Links: | ScriptParams(S...), ScriptParams([AR]@...), ScriptParams(MeantDest)
Schemas: | “`Event Activate`”
Parameters: | effect(string)

...

## TrapCamShift

Attach the camera to another object.

Script: | TrapCamShift
Inherits: | BaseTrap

This script will attach the camera to the script object. The camera is returned to the Player when the trap is deactivated.

The camera object cannot be changed in Thief 1.

In System Shock 2, the object you attach to must be given a unique name.

## TrapHP

Adjust the hitpoints of an object.

Script: | TrapHP
Inherits: | BaseTrap
Properties: | Game\Damage Model\Hit Points
Parameters: | hitcount(integer), target(object), culprit(object), damage(object)

Heals the target by hitcount points, which defaults to 1. Turning the trap off will damage the target by hitcount points. Hitcount can be negative, which would have the same effect as a positive value with the trap control flag Invert set. The source of the stim is the script object by default, you can change it with culprit. Damage sets the type of the stim.

## TrapMetaProp

Add or remove meta-properties.

Script: | TrapMetaProp
Inherits: | BaseTrap
Links: | ScriptParams(S...), ScriptParams([AR]@...)

This script will add or remove metaproperties on linked objects. Either operation can be performed when the trap is activated. First create a ScriptParams link to each metaproperty you want to add or remove. Set the data of each link to “`S`” followed by some key, such as a number or name. Each key should be different. Next create ScriptParams links to the objects you want to modify. Set the data of each link to either “`A@`” or “`R@`” followed by the key from one of the metaproperty links. When turned on, the objects with an “`A@`” link will have the referenced metaproperty added, and those with “`R@`” will have the metaproperty removed. Turning off the trap will do the opposite for each link.

## TrapMotion

Play a motion schema.

Script: | TrapMotion
Inherits: | BaseTrap
Parameters: | mot(string)

Put this script on an AI to make it play a specific motion when triggered. The name of the motion schema to play is specified in the mot parameter. It must be the motion name, like “`humgulp`”, and not the schema tags “`Drink 0`”.

## TrapPhantom

Gradually fade in/out.

Script: | TrapPhantom
Inherits: | BaseTrap
Links: | ControlDevice
Properties: | Renderer\Transparency (alpha)
Parameters: | alpha_min(float), alpha_max(float), rate(integer), curve(integer)

This script will manipulate the transparency of the object it’s on. When turned on, the object will become more visible, up to the value of alpha_max. Turning it off will make it transparent, stopping at alpha_min. The transparency level will change by the amount of rate every second. When the object becomes fully visible, a TurnOn is relayed along trigger links. TurnOff is relayed when it becomes invisible.

The curve parameter, which didn’t appear in the original version of this script, allows you to tweak the equation used to calculate the transparency. The transition is linear by default, which is a curve value of 0. The other equations are:

1: | `x2`
2: | `√x`
3: | `log x`
4: | `10x`
5: | `ln x`
6: | `ex`

## TrapScrMsgRelay

Convert TurnOn to any other message.

Script: | TrapScrMsgRelay
Inherits: | BaseTrap
Links: | ScriptParams(message)
Parameters: | status_index(integer), data(string), data1(string), data2(string), data3(string)

...

## TrapSMTrans

Convert any message to TurnOn.

Script: | TrapSMTrans
Inherits: | BaseTrap
Links: | ScriptParams(message)

...

## TrapStim

Stimulate linked objects.

Script: | TrapStim
Inherits: | BaseTrap
Links: | ControlDevice
Stimuli: | ScriptStim
Parameters: | stim(object), strength(integer)

...

## TrapTeleportDelta

Teleport an object maintaining relative position to a pair of reference objects.

Script: | TrapTeleportDelta
Inherits: | BaseTrap
Links: | ControlDevice, ScriptParams(dm)

...

## TrigAIAwareShift

Trigger when an AI becomes aware of an object.

Script: | TrigAIAwareShift
Inherits: | BaseScript
Messages: | DHNotify
Links: | AIAwareness, ScriptParams(af...), ScriptParams(av...), ScriptParams(aa...)

Requires dh2.osl.

## TrigBodyPickup

Send TurnOn when an object is picked up.

Script: | TrigBodyPickup
Inherits: | BaseScript
Messages: | Contained, TurnOn, TurnOff
Links: | ControlDevice

This script sends TurnOn when the object it is on is picked up. TurnOff is sent when it is dropped. Despite the name, the object doesn’t have to be an AI corpse.

## TrigDamageRTC

Trigger the object that causes damage.

Script: | TrigDamageRTC
Inherits: | BaseScript
Messages: | Damage, TurnOn

When the object is damaged, the source of the damage gets a TurnOn message sent back to it. The “RTC” stands for “return to culprit.”

## TrigOBBSpec

Trigger when certain types of objects enter a bounding-box.

Script: | TrigOBBSpec
Inherits: | BaseTrap
Messages: | PhysEnter, PhysExit, Obituary
Links: | ScriptParams(arc), ScriptParams(cd), Population
Metaproperties: | M-NotifyRegion

...

## TrigSim

Send TurnOn when the game starts.

Script: | TrigSim
Inherits: | BaseTrap
Messages: | Sim

This trigger activates once, when the game starts, and then it destroys itself.

## Validator

Relay to one in a list of objects.

Script: | Validator
Inherits: | BaseTrap
Messages: | Validate
Links: | ScriptParams(index)
Parameters: | order(string), increment(integer), rollover(integer)

...

## Zapper

Attack with a magical projectile.

Script: | Zapper
Inherits: | BaseScript
Messages: | EndAttack
Links: | AITarget
Stimuli: | MagicZapStim, Anti-Human
Schemas: | ghmagic, hit_magic, dam_sting, exp_cryopsi
Parameters: | zap_strength(float), no_zap_sound(boolean)

...

## Common Scripts

These scripts are useful in all games.

## BasePostRead

Common actions to be taken after a book is read.

Script: | PostReadPlaque
Inherits: | BaseTrap
Links: | SoundDescription, ControlDevice, SwitchLink
Properties: | Book\Text, Book\Art, Script\Use Message, Trap\Quest Var, Script\QBName, Script\Timing, Script\Delay Time, Sound\Object Sound

This is an abstract script for when an action should be taken after a book has been read. The advantage over traditional triggering methods is that the actions will always occur after the book-mode screen has been shown. This script can’t be used directly; use either PostReadPlaque or PostReadScroll instead.

The script can play a voice-over schema and set a quest variable. If both actions are being used, then the quest variable is changed after the schema plays. Specify the schema to play by creating a SoundDescription link, which can be on an archetype of the object. Unfortunately, the script can’t tell on its own when a voice-over has finished playing. So set the Script\Timing property to the length of the schema.

After the voice-over has played or, if no schema was specified, after the book is read, a quest variable is modified. The name and operation are specified in the Trap\Quest Var property. The same options as for TrapMissionQVar.

You can also use trigger links with this script. They will be activated when the book is read.

System Shock 2 doesn’t have a book-mode, so this script isn’t as useful as in a Thief game. The text to display is determined by the Script\Use Message property. Set the voice-over schema name with the Sound\Object Sound property, and use the Script\Delay Time property. The quest variable is specified with the Script\QBName property using the same format.

## BaseQVarText

Abstract script for displaying text with quest-variable substitutions.

Script: | BaseQVarText
Properties: | Book\Text, Script\Use Message

This script displays text on-screen that can include the values of quest variables. The text to display, which is specified by the Book\Text or Script\Use Message property, is scanned for replaceable sub-strings. Each sub-string is evaluated and a replacement made. The replacements themselves may contain further replacements, and those will be processed as well. When all of the sub-strings have been found, the text is displayed. This only works for on-screen text, so the Book\Art property is ignored.

This script can’t be used directly. You can use QVarPlaque, QVarScroll, or TrapQVarText depending on how you want the script to be triggered.

Each replaceable sub-string begins with the character ‘`%`’ and then the name of the quest variable enclosed in curly braces (‘`{`’ and ‘`}`’). This will insert the value of the quest variable in place of the sub-string. Instead of the value, other text can be inserted by adding a conditional character before the braces. The possible conditions are ‘`=`’, ‘`<`’, ‘`>`’, and ‘`?`’. After the curly braces, write one or two sets of square brackets (‘`[`’ and ‘`]`’) with the new text in each. The first set will be printed if the condition is true, and the optional second set will be printed if it is false.

The ‘`=`’, ‘`<`’, and ‘`>`’ conditionals test if the quest variable is equal to, less than, or greater than some number. Write the number to compare to immediately after the conditional character. The last conditional, ‘`?`’, just tests if the variable is non-zero.

The following example prints the value of the quest variable `bottles` if it is not zero, or the text “`No more`” if it is zero. Then the word “`bottle`” is pluralized if necessary.

`%?{bottles}[%{bottles}][No more] bottle%=1{bottles}[][s] of beer on the wall.`

## PostReadPlaque

Perform actions after reading a book in the world.

Script: | PostReadPlaque
Inherits: | BasePostRead
Messages: | FrobWorldEnd

This is for books that are frobbed in the world. The actions that occur are described in BasePostRead.

## PostReadScroll

Perform actions after reading a book in the inventory.

Script: | PostReadScroll
Inherits: | BasePostRead
Messages: | FrobInvEnd

This is for books that are frobbed in the inventory. The actions that occur are described in BasePostRead.

## QVarPlaque

Display text when frobbed in the world.

Script: | QVarPlaque
Inherits: | BaseQVarText
Messages: | FrobWorldEnd

This script activates when the object is frobbed in the world. The text is displayed as described in BaseQVarText.

## QVarScroll

Display text when frobbed in inventory.

Script: | QVarScroll
Inherits: | BaseQVarText
Messages: | FrobInvEnd

This script activates when the object is frobbed in the inventory. The text is displayed as described in BaseQVarText.

## Transmogrify

An object that becomes something else when picked up.

Script: | Transmogrify
Inherits: | BaseScript
Messages: | Contained
Links: | Transmute, Mutate

This script lets you make objects that act like the crystals from Thief. There are two types of objects: one that appears in the world, and another for the inventory. This script goes on the object that is created in the world. When the object is picked up by the Player, it will create the other type of object and put that in the inventory instead. The link that associates the two objects can be placed on the archetypes, which makes it easy to implement different types of transmogrifying objects.

Thief: Link the objects using a Transmute link.

SS2: Link the objects using a Mutate link.

## TrapCampaignQVar

Set a quest variable in the campaign database.

Script: | TrapCampaignQVar
Inherits: | TrapMissionQVar

The quest variable that this trap sets will be saved in the campaign database, so it can be read in later missions as well. The variable actually gets written to the mission database first, and only gets moved when the game ends. Trust me, this is the best way to make the script work. Just don’t be surprised if DromEd doesn’t always show the variable in the campaign database.

In System Shock 2, the default for most scripts is to store quest variables in the campaign database. The hack described above does not apply in SS2.

## TrapCinema

Play a movie.

Script: | TrapCinema
Inherits: | BaseTrap
Parameters: | movie(string)

When activated, an AVI movie is played. The parameter movie is the filename of the file to view. It will be looked for in the movies directory, or whatever your movie_path is set to.

## TrapDestroyDoor

Destroy a door the right way.

Script: | TrapDestroyDoor
Inherits: | BaseTrap
Messages: | TurnOn
Links: | ControlDevice, SwitchLink

Doors are difficult to destroy by ordinary means. Traps that slay an object will only make the door pop open. And teleporting a door away will leave behind the black rectangle when the Blocks Vision? flag is on. This script will make sure a door is really destroyed, and leaves the portal open. The doors to destroy are linked to using ControlDevice or SwitchLink links.

## TrapFader

Fade the screen in and out.

Script: | TrapFader
Inherits: | BaseTrap
Parameters: | fade_time(time), fade_color(color)

The screen will fade out when this trap is turned on. Turning off the trap will fade the screen back in. You should always use the revert timer with this trap so the screen doesn’t get stuck in the fade-out. The fade_time is the time it will take for the screen to fade completely in or out. When using the revert feature of the trap, the timer will start at the same time as the fade. So you should set it to at least the same length as fade_time.

Thief 1: The screen will not fade in, but will just instantly reappear.

Thief 2: Fading in will make the player unwield any weapons.

SS2: The color of the fade can be changed with the fade_color parameter. The default is black.

The configuration setting no_endgame prevents this script from working.

## TrapFlipFlop

Alternate between TurnOn and TurnOff.

Script: | TrapFlipFlop
Inherits: | BaseScript
Messages: | TurnOn, TurnOff

This trap only responds to TurnOn. Each time it is triggered, it will send either TurnOn or TurnOff, alternating between the two. The Invert and Once trap control flags will be used.

## TrapMissionQVar

Sets a quest variable, with complete arithmetic operations.

Script: | TrapMissionQVar
Inherits: | BaseTrap
Properties: | Trap\Quest Var, Script\QBName
Parameters: | initqv(integer)

When activated, the script will modify the value of a quest variable. The variable name and operation to perform are specified in the Trap\Quest Var or Script\QBName property. The quest variable is stored in the mission database. Thief games can also write the variable to the campaign database using TrapCampaignQVar.

The operation format is the same as from TrapSetQVar from Thief. First is a single-character operation, followed by an integer argument to the operation. Then there is a colon (‘`:`’) followed by the name of the quest variable. There should be no spaces up until the variable name. Spaces are allowed in the name, however. The following table explains the possible operations, and includes an example of what happens when the trap is activated with a certain argument. In all cases, the original value of the quest variable is 102.

Quest Variable Trap Operations

Op | Turn On | Turn Off | Example
--- | --- | --- | ---
`=` | Sets the value to the argument. | Sets the value to 0. | `=3` → `3`
`+` | Adds the argument to the value. | Subtracts the argument from the value. | `+3` → `105`
`-` | Subtracts the argument from the value. | Adds the argument to the value. | `-3` → `99`
`*` | Multiplies the value by the argument. | Divides the value by the argument. | `*3` → `306`
`/` | Divides the value by the argument. | Multiplies the value by the argument. | `/3` → `34`
`%` | Takes the remainder of the value divided by the argument. | Multiplies the value by the argument. | `%4` → `2`
`|` | Performs bitwise-or with the value and the argument. | Clears the bits in the value that are set in the argument. | `|3` → `103`
`{` | Shifts the bits in the value to the left. | Shifts the bits in the value to the right. | `{3` → `816`
`}` | Shifts the bits in the value to the right. | Shifts the bits in the value to the left. | `}3` → `12`
`"` | Multiplies the value by 10, then adds the least-significant decimal digit of the argument to the variable. | Divides the value by 10. | `"3` → `1023`
`#` | Multiplies the value by 10, then adds the least-significant decimal digit of the argument to the variable. The value will always be less than 10000. | Divides the value by 10. | `#31` → `1021`
`?` | Adds to the value a random number ≥ 0 and ≤ the argument. | Subtracts from the value a random number ≥ 0 and ≤ the argument. | `?3` → `102—105`
`d` | Adds to the value a random number > 0 and ≤ the argument. | Subtracts from the value a random number > 0 and ≤ the argument. | `d3` → `103—105`

You don’t have to create the quest variable ahead of time with this script. If the parameter initqv is set, then the variable will be set to that value when the game starts.

## TrapQVarFilter

Relay if a quest-variable meets the requirement.

Script: | TrapQVarFilter
Inherits: | BaseTrap
Properties: | Trap\Quest Var, Script\QBName

This script will relay messages if a quest variable condition is met. Set the Trap\Quest Var or Script\QBName property like TrigQuestVar. Then, when the test is true, the relay will pass messages.

## TrapQVarText

Display text when turned on.

Script: | TrapQVarText
Inherits: | BaseQVarText
Messages: | TurnOn

When this trap is activated it displays text as described in BaseQVarText.

## TrapRequireOne

Trigger when an odd number of switches is turned on.

Script: | TrapRequireOne
Inherits: | BaseTrap
Links: | ScriptParams(Require)

This script combines the outputs of multiple triggers so that when any one of the triggers changes state, the state of the trap changes. With only two sources, this is called a three-way switch; but this trap can have any number of sources. In particular, the trap is turned on when an odd number of triggers has been turned on. The triggers that are turned on are tracked using ScriptParams links that have the data set to “Require”.

## TrapRequireOneOnly

Trigger when just one switch is turned on.

Script: | TrapRequireOneOnly
Inherits: | BaseTrap
Links: | ScriptParams(Require)

This trap will be turned on when exactly one of its triggers is turned on. The triggers that are turned on are tracked using ScriptParams links that have the data set to “Require”.

## TrapTimer

A simple timer.

Script: | TrapTimer
Inherits: | BaseTrap
Properties: | Script\Timing, Script\Delay Time

A timer is the most useful type of trap that isn’t present in most of the standard games. What were they thinking? Set the time to delay the message in Script\Timing (as milliseconds) or in Script\Delay Time (as seconds). The extra data of the message will not be preserved.

This trap works like the standard TrapRelay in that it will pass not just TurnOn and TurnOff, but other (though not all) types of messages as well.

## TrigOBBCreature

Trigger when an AI enter a bounding-box.

Script: | TrigOBBCreature
Inherits: | TrigOBBSpec
Messages: | PhysEnter, PhysExit
Links: | Population

This is an OBB trigger, also known as a tripwire, that triggers when an AI enters the bounding-box of the object. Actually, it reacts to objects of type Creature (Thief) or Monsters (SS2). The creature is tracked the same way as for TrigOBBSpec.

## TrigQuestVar

Trigger when a quest variable changes.

Script: | TrigQuestVar
Inherits: | BaseTrap
Messages: | QuestChange
Properties: | Trap\Quest Var, Script\QBName

When the value of a quest variable changes, this script tests it against a condition and sends TurnOn when the condition becomes true, or TurnOff if it is now false. (Or it sends nothing if the condition hasn’t changed.) The possible tests are the same as in Thief 2, so there’s no difference between this script and TrigQVar in that game.

The condition in the Trap\Quest Var or Script\QBName property is similar to that used by TrapMissionQVar. The first character is the type of the test, ‘`=`’, ‘`<`’, ‘`>`’, ‘`&`’, or ‘`"`’. Following this is the number to test against, then a colon (‘`:`’) and finally the name of the quest variable. There should not be any spaces from the start of the string up to the name of the variable. (Variables names can have spaces in them.)

The tests ‘`=`’, ‘`<`’, and ‘`>`’ test if the quest variable is equal-to, less-than, or greater-than the given number. The ‘`&`’ test compares the numbers as a set of binary bits. If any of the bits set in the test number are also set in the quest variable, the condition is true. The ‘`"`’ test compares the decimal digits of the numbers. The quest variable must have the same digits in the same places as the test number. Digits greater than those in the test number are ignored. You can test against 0, even in the leading digits. (So testing against “`01`” is actually different than testing against just “`1`”.)

## TrigWaypoint

Trigger when a moving terrain object reaches the waypoint.

Script: | TrigWaypoint
Inherits: | BaseScript
Messages: | WaypointReached
Links: | ControlDevice

Put this script on a TerrPt and it will activate its trigger links when the moving terrain object reaches it.

## Thief 1 Scripts

Scripts for Thief: The Dark Project and Thief Gold. These are mostly ports of scripts from Thief 2.

## CleanUpAttack

Disable an attack SFX when an AI is knocked-out.

Script: | CleanUpAttack
Inherits: | BaseScript
Messages: | AIModeChange, AbortAttack

The standard scripts don’t properly handle the case of an AI being knocked-out while in the middle of an attack. To make sure that the attached SFX are disabled, use this script alongside AttackActivate.

## FrobFind

Reveal a secret when the object is frobbed.

Script: | FrobFind
Inherits: | BaseScript
Messages: | FrobWorldEnd
Properties: | Dark GameSys\Stats
QVars: | DrSSecrets, DrSScrtCnt

Adds to Thief 1 the ability to count secrets in a mission. The number of secrets is automatically tallied when the game begins. This script will mark a secret as having been found when the object is frobbed in the world. You also have to set the Hidden flag on the Dark GameSys\Stats property.

## HiddenDoor

Reveal a secret when the door is opened.

Script: | HiddenDoor
Inherits: | BaseScript
Messages: | DoorOpen
Properties: | Dark GameSys\Stats
QVars: | DrSSecrets, DrSScrtCnt

Adds to Thief 1 the ability to count secrets in a mission. The number of secrets is automatically tallied when the game begins. This script will mark a secret as having been found when the door is opened. You also have to set the Hidden flag on the Dark GameSys\Stats property.

## InvisiPotion

Makes the player invisible when used.

Script: | InvisiPotion
Inherits: | TimedPotion
Messages: | Invisible, Visible
Properties: | AI\State\Current visibility
Metaproperties: | M-Invisible

When this potion is used by the Player, then he will be made invisible using the metaproperty M-Invisible. The metaproperty only needs to include a Scripts with Invisible in it.

The Renderer\Invisible doesn’t exist in Thief 1, so the player’s weapon doesn’t disappear like in Thief 2.

## Invisible

Makes the object invisible.

Script: | Invisible
Inherits: | BaseScript
Messages: | Invisible
Links: | AIAttack
Properties: | AI\State\Current visibility

This script is activated by the message Invisible, which is sent by the InvisiPotion script. The object will be made invisible to AI.

## LastMissionLoot

Use the loot collected in the previous mission.

Script: | LastMissionLoot
Inherits: | BaseScript
Messages: | Difficulty
Properties: | Dark Gamesys\Loot, Difficulty\Script
QVars: | total_loot

This script will set the object’s Dark Gamesys\Loot property to the amount of loot collected in the previous mission. To activate it, you need to add the Difficulty\Script property and set the flags for which difficulty levels you want to use the script on. If the script isn’t activated, then the Dark Gamesys\Loot property is left unmodified.

## LoGravPotion

Decreases the player’s gravity and movement speed when used.

Script: | LoGravPotion
Inherits: | TimedPotion
Properties: | Physics\Model\Attributes

When this potion is used by the Player, his speed and gravity will be cut in half. Multiple uses don’t affect the overall speed and gravity, but instantaneous speed is reduced each time.

## NoPingBack

Ignore mines when the AI is disabled.

Script: | NoPingBack
Inherits: | BaseScript
Messages: | AIModeChange
Metaproperties: | NoPingBack

When the AI is knocked-out or killed, the NoPingBack metaproperty is added to it. The metaproperty should contain a PingStim receptron with no limit an an effect of Abort.

## NonAutoDoor

A door that remains closed when unlocked.

Script: | NonAutoDoor
Inherits: | BaseScript
Messages: | DoorOpen, DoorClose, DoorOpening, DoorClosing, DoorHalt, TurnOn, TurnOff, FrobWorldEnd, Slain, NowLocked, NowUnlocked, SynchUp, PlayerToolFrob
Links: | ScriptParams(Double)
Properties: | Door\Rotating, Door\Translating, Engine Features\Locked
Schemas: | “`Event StateChange, OpenState, OldOpenState`”, “`Event Reject, Operation OpenDoor`”

Just like the StdDoor script, but when the door is unlocked it remains closed.

## NoticesPlayerBumps

Become alerted when bumped by the player.

Script: | NoticesPlayerBumps
Inherits: | BaseScript
Messages: | PhysCollision
Properties: | AI\AI Core\Alertness cap

When the Player object collides with this AI, its alert level will momentarily be raised to level 2. Thief 2 has this on the robots. I don’t know why it isn’t on all AI.

## PhysARContact

Stimulate objects that touch this one.

Script: | PhysARContact
Inherits: | BaseScript
Messages: | PhysContactCreate, PhysContactDestroy

When an object touches this one, it will receive any contact stimuli from it.

This is actually the same as the HotPlate script from Thief Gold, but I’m including it for the sake of completeness.

## ReGravitize

Set the object’s gravity when touched.

Script: | ReGravitize
Inherits: | BaseScript
Messages: | PhysCollision
Properties: | Physics\Model\Attributes

When something collides with this object, its gravity is set to 3.2578125. I honestly don’t know why.

## ShutUpYerDead

Cancels an AI’s behavior when it is killed.

Script: | ShutUpYerDead
Inherits: | BaseScript
Messages: | IgnorePotion
Links: | AIAwareness

This script should be part of the M-KnockedOut metaproperty. It activates automatically. The AIAwareness links will be reset, and the message IgnorePotion is sent to the object.

## SlayFind

Reveal a secret when the object is slain.

Script: | SlayFind
Inherits: | BaseScript
Messages: | Slain
Properties: | Dark GameSys\Stats
QVars: | DrSSecrets, DrSScrtCnt

Adds to Thief 1 the ability to count secrets in a mission. The number of secrets is automatically tallied when the game begins. This script will mark a secret as having been found when the object is slain. You also have to set the Hidden flag on the Dark GameSys\Stats property.

## SlayHaltSpeech

Silence an AI when killed.

Script: | SlayHaltSpeech
Inherits: | BaseScript
Messages: | Slain

Halts the AI’s current speech when it is slain. Thief 2 uses this on frogs and rats.

## TimedPotion

A generic potion with a timed activation period.

Script: | TimedPotion
Inherits: | BaseScript
Messages: | FrobInvEnd, StartPotion
Links: | ScriptParams(Potion)
Properties: | Script\Timing, Engine Features\Combine Type
Schemas: | “`Event Deactivate`”

This script is used for potions that activate when frobbed in the inventory. The potion will be active for a specified period of time. Using another potion of the same type will restart the timer. The duration of the potion is specified with the Script\Timing property in milliseconds. The default time is 8.6 seconds, and the potion will always last at least 1 second. The environmental schema tags “`Event Deactivate`” will be played just before the potion ends. This script doesn’t make any sound when the potion begins, though.

If the object is in an AI’s inventory when the game starts, then the metaproperty M-QuaffHeal is added to the AI. This already exists in Thief 1, so you don’t have to create it yourself.

## TransformLock

Change an object’s shape when unlocked.

Script: | TransformLock
Inherits: | BaseScript
Messages: | NowUnlocked
Properties: | Tweq\Models, Engine Features\KeyDst

When this object is unlocked, the model tweq will be activated. It also disables the lock by setting the Region Mask to 0.

## TrapDirection

Control a tweqable object.

Script: | TrapDirection
Inherits: | BaseTrap
Messages: | GoForward, GoReverse
Links: | ControlDevice

This trap converts TurnOn and TurnOff messages into GoForward and GoReverse. The messages are relayed along ControlDevice links. The TweqOnOff script can be used on the controlled object to respond to these messages.

## TrapFindSecret

Reveal a secret when the trap is activated.

Script: | TrapFindSecret
Inherits: | BaseTrap
Properties: | Dark GameSys\Stats
QVars: | DrSSecrets, DrSScrtCnt

Adds to Thief 1 the ability to count secrets in a mission. The number of secrets is automatically tallied when the game begins. This script will mark a secret as having been found when the trap is turned on. You also have to set the Hidden flag on the Dark GameSys\Stats property.

## TrapNonFinalComplete

Trigger when a mission is almost over.

Script: | TrapNonFinalComplete
Inherits: | BaseTrap
Messages: | Sim, QuestChange
QVars: | goal_state_*, goal_visible_*

This trap monitors the objective quest variables. When all of the visible objectives, except for those marked as “final” or “optional”, have been completed, then the trigger is turned on.

## TrapOffFilter

Only relay TurnOff messages.

Script: | TrapOffFilter
Inherits: | BaseScript
Messages: | TurnOff

This is an old-fashioned relay that only passes TurnOff. It doesn’t support any of the more advanced trap features.

## TrapOnce

Relay a message one time only.

Script: | TrapOnce
Inherits: | BaseScript
Messages: | TurnOn, TurnOff

This is an old-fashioned trap that will relay a single TurnOn or TurnOff only. It doesn’t support any of the more advanced trap features.

## TrapPatroller

Activate AI patrol routes.

Script: | TrapPatroller
Inherits: | BaseTrap
Links: | ControlDevice
Properties: | AI\Ability Settings\Patrol: Does patrol

This trap activates and deactivates the patrol property of all the AI that it is linked to. The standard TrapPatrol script of Thief 1 only changes the property on one object at a time.

## TrapRevert

Automatically turn off after being turned on.

Script: | TrapRevert
Inherits: | BaseScript
Messages: | TurnOn, TurnOff, Timer
Properties: | Script\Timing

This is an old-fashioned trap. It relays a TurnOn or TurnOff message then, after a period of time, sends the opposite message. The time is specified in the Script\Timing property as milliseconds. If it is not present, or is 0, then the trap acts like a normal relay. Sending a message while the timer is active will cancel the previous timer.

## TrapSlayer

Slay an object using a stimulus.

Script: | TrapSlayer
Inherits: | BaseTrap
Links: | ControlDevice
Properties: | Game\Damage Model\Hit Points
Stimuli: | BashStim

This trap will slay linked objects by damaging them with a BashStim. The hit-points of the object is set to 1 first, so the damage results in death. If this isn’t done, the object won’t do some things, such as playing a schema or leaving a corpse behind.

## TrapTerminator

Destroy objects when activated.

Script: | TrapDestroy
Inherits: | BaseTrap
Links: | ControlDevice

The standard TrapDestroy script doesn’t really destroy all objects. This script, when activated, will destroy all ControlDevice linked objects, no questions asked.

## TrapTexture

Change the texture of terrain.

Script: | TrapTexture
Inherits: | BaseTrap
Properties: | Script\TerrReplaceOn, Script\TerrReplaceOff, Engine Features\Retexture Radius

This trap controls the texture of nearby terrain. Set the properties to the path to the texture resource for when the trap is turned on and when it is turned off. The destroyed texture isn’t supported by this script. Any cells within the retexture radius will have their polygons swapped between the old and new textures. You need to have the textures initially set to the same state as the trap. Changing textures won’t work if the new texture isn’t also loaded into the mission.

## TrigOBBPlayer

Trigger when the player enters a region.

Script: | TrigOBBPlayer
Inherits: | BaseTrap
Messages: | PhysEnter, PhysExit
Schemas: | “`Event Activate`”, “`Event Deactivate`”

This trap triggers when the Player object enters the bounding-box dimensions of the object. The properties of the object should be set like the standard BoundsTrigger trap. Of course, you’ll want to modify the dimensions to the appropriate size. An environmental schema with tags “`Event Activate`” will be played when the trap turns on, and “`Event Deactivate`” when turned off.

## TrigRoomDelivery

Trigger when the player carries an object into a room.

Script: | TrigRoomDelivery
Inherits: | TrigRoomObject
Messages: | Contained

Put this script on an object and it will trigger when it is carried into a room by the Player. The trigger turns off if the object is dropped, even inside a target room. The object is linked to the target rooms with Route links.

## TrigRoomDeposit

Trigger when the object is dropped in a room.

Script: | TrigRoomDeposit
Inherits: | TrigRoomObject
Messages: | Contained

Put this script on an object and it will trigger when dropped in a specific room. The trigger turns off if the object leaves the room, or is picked up again. The object is linked to the target rooms with Route links.

## TrigRoomObject

Trigger when an object enters a room.

Script: | TrigRoomObject
Inherits: | BaseScript
Messages: | ObjRoomTransit
Links: | ControlDevice, Route

Put this script on an object and it will trigger when entering a target room. You can specify any number of target rooms using Route links.

## TrigRoomPopChange

Trigger when someone enters or exits a room.

Script: | TrigRoomPopChange
Inherits: | BaseScript
Messages: | CreatureRoomEnter, CreatureRoomExit, PlayerRoomEnter, PlayerRoomExit
Links: | ControlDevice

This script is for room objects. It sends a TurnOn message anytime an AI or the Player enters or leaves the room.

## Thief 2 Scripts

Scripts for Thief 2: The Metal Age. Many of these scripts originally appeared in Thief 1.

## Burplauncher

Helper for burrick gas clouds.

Script: | Burplauncher
Inherits: | BaseScript
Messages: | Slain
Links: | Firer

This script is meant to be put on the burplauncher object that is emitted by burricks. When any part of the cloud of gas collides with something else, this script will destroy all other parts of the cloud. However, burplauncher works just fine without the script, and the difference isn’t very noticeable.

## CleanObjDestroy

Destroy objects when they aren’t visible.

Script: | CleanObjDestroy
Inherits: | BaseTrap
Messages: | TurnOn
Links: | ControlDevice

This trap will destroy objects in a way that the player doesn’t see them disappear. Objects that are currently visible, or are being carried by the player, will be skipped. The script continues to check every few seconds until all linked objects have been destroyed.

## CollapseFloor

An object that will fall down when stepped on.

Script: | CollapseFloor
Inherits: | BaseScript
Messages: | PressurePlateActive
Links: | Corpse, Flinderize
Properties: | Physics\Misc\Pressure Plate

A collapsing floor is a type of pressure plate. The object is usually placed above a pit. You can configure the Physics\Misc\Pressure Plate however you like. A slower speed and longer travel distance will give the player time to get off of the collapsing section before it falls. When the object is fully depressed, it will be destroyed. To make the object appear to fall to the bottom of the pit, you need to create a separate archetype for the falling object. Create a Corpse link from the collapsing floor to the falling object. You can also use Flinderize links for falling objects that will be scattered.

## ControlWindowShade

An animated light that automatically turns on and off.

Script: | ControlWindowShade
Inherits: | WindowShade
Messages: | Sim
Properties: | Script\Timing
Parameters: | auto_time_min, auto_time_max

This is a variation of WindowShade that also periodically turns the light on or off. The time between changes is randomly selected, between 5 and 15 seconds by default. This can be changed with the auto_time_min and auto_time_max parameters. Whether the light will be changed to on or to off depends on the Script\Timing property. This number is the probability that the light will be turned on. A value of 100 or greater will keep the light turned on all the time.

## ConvControl

Controller for complex multi-part conversations.

Script: | ConvControl
Inherits: | BaseScript
Messages: | TurnOn, TurnOff, NowLocked, NowUnlocked, Presence, Absence, Intrusion, Privacy, ConvNext, ConvEnd
Links: | ControlDevice

This script allows you to make complex multi-part conversations that can be interrupted and resumed. The controller is linked to a number of conversation traps. When the controller is turned on, it will trigger the first of the linked conversations. One of the conversation actors should have the ConvSpeaker script so it can send a ConvNext message back to the controller. When this happens, the controller will remove the link to the conversation that was just triggered and proceed to the next one. This continues until an actor sends ConvEnd, or if the controller is turned off.

A locked controller does not trigger any conversation. If the controller is turned on while locked, or was turned on when it became locked, then it will continue the conversations once it is unlocked.

The messages Presence and Absence are also accepted and will turn the controller on and off, respectively. The message Intrusion will act like locking the controller, and Privacy is like unlocking it.

## ConvSpeaker

Allow an AI to perform complex conversation actions.

Script: | ConvSpeaker
Inherits: | BaseScript
Messages: | ConvNext, ConvEnd, Slay, PlayVO, PlayAmbient, CompleteGoal, FailGoal, CancelGoal, ShowGoal, HideGoal, SwapGoal, IsGoalShown, IsGoalComplete

This script responds to messages from an AI involved in a conversation or other pseudo-script. Add this script to the AI and use the action Script message with the message name as the first argument. Some of these messages use the other arguments of the command. Where the description mentions the “first argument”, it is referring to the arguments the message receives, which are offset by one in the pseudo-script action dialog box. So you’d type the “first” argument for the message as the second argument for the action.

ConvNext, ConvEnd : | Relay the message to the controller of a conversation. Meant to be used with ConvControl. The controller object will be located automatically, but you can specify a specific object as the first argument.
PlayAmbient, PlayVO : | Play a schema as either an ambient sound, or as a voice-over. The first argument is the name of the schema object.
Slay : | Slays a specified argument. Leave the argument blank, or type “`self`” to slay this AI. Otherwise, the argument is the object to slay.
CompleteGoal, FailGoal, CancelGoal : | Changes the state of an objective. The argument is a comma (‘`,`’) separated list of objective numbers that will be modified.
ShowGoal, HideGoal : | Changes the visibility of an objective. The argument is a comma (‘`,`’) separated list of objective numbers that will be modified.
SwapGoal : | Simultaneously makes one objective visible and hides another. This message takes two arguments; both comma (‘`,`’) separated lists of objective numbers. The first argument is the objectives to hide, and the second is the objectives to show.
IsGoalShown, IsGoalComplete : | Checks if an objective is visible or if it is completed. The argument is a comma (‘`,`’) separated lists of objective numbers. If any of the objectives are hidden or incomplete, then the pseudo-script stops.

## CorpseFrobFixed

Lets you pick up AI after they have been disabled.

Script: | CorpseFrobFixed
Inherits: | BaseScript
Messages: | AIModeChange, Slain, FrobWorldEnd
Metaproperties: | FrobInert

The standard script CorpseFrobHack doesn’t work with AI that contain unfrobbable objects. This replacement fixes that problem.

## CuttyCell

Trigger for complex conversations.

Script: | CuttyCell
Inherits: | BaseScript
Messages: | PlayerRoomEnter, PlayerRoomExit, Presence, Absence

This is a room script that generates the Presence and Absence message for the ConvControl script. It activates when the Player enters or leaves the room.

The controller can also be triggered with standard TurnOn and TurnOff messages, so this script isn’t really necessary.

## Elemental

An object that can grow and shrink when damaged.

Script: | Elemental
Inherits: | BaseScript
Messages: | Damage, Slain
Properties: | Shape\Scale, Tweq\Scale, Tweq\ScaleState
Parameters: | health_curve(integer)

This script will adjust the Shape\Scale to match the health of the object. Add the Tweq\Scale property to the object and it will shrink when slain.

The health_curve parameter modifies the relationship between the health of the object and its size. See the description of TrapPhantom for the possible values.

## FactoryBase

Abstract script for factory switches.

Script: | FactoryBase
Inherits: | BaseScript
Messages: | TweqComplete, TurnOn, TurnOff, SynchUp, Target?
Links: | ControlDevice, ScriptParams(ErrorOutput), FrobProxy
Properties: | Tweq\Joints, Tweq\JointState
Schemas: | “`Event StateChange DirectionState ...`”

The objects that are used in factory set-ups share many actions. Because most of the objects are levers, or act similarly to levers, this script mostly does all the things that you would expect from the StdTwoState script, such as activating tweqs, environmental schemas, and sending TurnOn and TurnOff messages.

A typical factory uses one cauldron, two levers, a gauge, one mold, and a product. Optional devices include, a buzzer, a mold socket, a gear, and sparks. With a worker, the factory can be automated. See the scripts for each individual device for specific directions.

## FactoryCauldron

Controller for a cauldron in a factory.

Script: | FactoryCauldron
Inherits: | FactoryBase
Links: | ScriptParams(Synch), ScriptParams(Sparks)
Properties: | Tweq\Models, Renderer\AnimLight
Schemas: | cauldron_lp, lava_pour, cauldron_pivot

A cauldron is a lever that, when on, indicates that molten iron is being poured into a mold. It has a joint tweq for tilting, and a model tweq for showing pouring iron. It can also be illuminated while pouring.

A cauldron is normally activated by a lever using a ControlDevice link. The cauldron should link to a gauge using ControlDevice. While moving forwards or backwards, it will turn a gear that is linked using ScriptParams links with the data “Synch”. The gear should use the script TweqOnOff. While pouring, a particle SFX can be activated. Link to the SFX using a ScriptParams link with the data “Sparks”. If the factory is automated, the worker AI must link to the cauldron using Owns.

## FactoryGauge

Controller for a gauge in a factory.

Script: | FactoryGauge
Inherits: | FactoryBase
Messages: | Halt, Full
Links: | ScriptParams(Mold)
Parameters: | rates(float,float,float), overflow(float)

A gauge in a factory indicates when a mold has been filled. The joint tweq of the gauge can be in three stages: rising, overflow, and falling. The speed of the tweq in each stage must be set using the parameter rates set to three floating-point values separated by commas. You also configure the Tweq\Joints property for the first stage. After the first stage, the gauge will continue moving forward at the speed from the second value in rates, and will add the value of overflow to the “high” position of the tweq. After the second stage, the tweq will reverse and return to the “low” position at the third speed from rates. The default rates are “`1.75,0.5,30`” and the default overflow is “`20`”.

When the gauge goes from the first to the second stage, it will send the message Full along ScriptParams links that have the data set to “Mold”. This link should point to the factory mold. It sends TurnOn along ControlDevice links after the second stage. This message should pass through an Inverter to turn off the lever that controls the cauldron. Another link can also go to a buzzer. It does not send TurnOff at any time.

## FactoryLever

A lever in a factory.

Script: | FactoryLever
Inherits: | FactoryBase
Messages: | FrobWorldEnd
Links: | ScriptParams(LockMe)

A factory lever uses locks to prevent it from being toggled at inappropriate times. There are typically two factories in each factory: one controlling a cauldron and one controlling a mold. The lever will link to the controlled object using ControlDevice. Each lever has an associated FnordLock that the lever links to using Lock. There should also be a ScriptParams link with the data “LockMe” from each lever to the lock for the other lever. The lever can also link to a buzzer using a ScriptParams link with the data set to “ErrorOutput”. This will be used if the lever is frobbed while it is locked.

## FactoryLight

A light that automatically turns off.

Script: | FactoryLight
Inherits: | BaseScript
Messages: | TurnOn, TurnOff
Properties: | Renderer\Render Type, Renderer\AnimLight, Script\Timing
Schemas: | “`Event Activate`”

A factory light is most often used as a buzzer. When activated, the light will turn on and play a schema. After the time set in Script\Timing, the light will turn off. If Script\Timing is not set, then the light will be on for 550 milliseconds.

The object doesn’t have to use Renderer\AnimLight. Without the property, the “light” will be turned on by setting the Renderer\Render Type to Unlit, and turned off by resetting it to Normal.

## FactoryMold

...

Script: | FactoryMold
Inherits: | FactoryLever
Messages: | FrobToolEnd, Contained, SocketMe, UnsocketMe, Full, Full?
Links: | ScriptParams(Mold), Owns, Contains
Properties: | Physics\Model\Attributes

...

## FactoryWork

...

Script: | FactoryWork
Inherits: | BaseScript
Messages: | ObjActResult, MotionEnd, Alertness, AIModeChange, Slain, Report
Links: | Owns, Route, ScriptParams(WithHammer)
Metaproperties: | M-FactoryWorker, M-WithHammer
Objects: | TrolPt, Molds, Hammers, SmeltingCauldr
Parameters: | frobmotion(string), pickupmotion(string), dropmotion(string)

...

## FireElemSparx

Adjust the color of a SFX.

Script: | FireElemSparx
Inherits: | BaseScript
Messages: | TurnOn, TurnOff, Mood0, Mood1, Mood2, Mood3, Die
Properties: | SFX\Particles

The FireElement sends messages to its attached SFX indicating the alert level of the AI. This script adjusts the color of the particles based on those messages.

## FireElement

An AI made out of fire.

Script: | FireElement
Inherits: | Elemental
Messages: | Damage, Alertness, Mood0, Mood1, Mood2, Mood3
Properties: | Renderer\Dynamic Light, Renderer\Extra Light, Renderer\Transparency
Metaproperties: | BigHeatSource
Stimuli: | WaterStim
Objects: | FElemHit, SteamPuff

A fire elemental glows brighter when alerted, generates extra heat at high alert, and is damaged by water. Fire elementals can be created without using this script, but they’re much better with it.

## HeStartedIt

Wake up AI when the player attacks.

Script: | HeStartedIt
Inherits: | BaseScript
Messages: | Damage, Slain
Metaproperties: | M-Swaying Burrick
Stimuli: | Knockout

If the Player damages or knocks out this AI, then the metaproperty M-Swaying Burrick will be removed from all creatures.

## Horn

Wake up AI when grabbed.

Script: | Horn
Inherits: | BaseScript
Messages: | Contained
Properties: | AmbientHacked
Metaproperties: | M-Swaying Burrick

Removes the metaproperty M-Swaying Burrick from all creatures when this object is picked up. It also disables the ambient schema on the object.

## HotPlate

Stimulate objects that touch this one.

Script: | HotPlate
Inherits: | BaseScript
Messages: | PhysContactCreate, PhysContactDestroy

When an object touches this one, it will receive any contact stimuli from it.

This is actually the same as the PhysARContact script.

## HotPlateControl

Toggles the state of hot plates.

Script: | HotPlateControl
Inherits: | BaseScript
Messages: | TweqComplete
Links: | ControlDevice
Properties: | Tweq\Joints, Tweq\Flicker, Shape\Joint Positions, Renderer\Extra Light
Metaproperties: | HotPlateHeat

This script uses a combination of a joint tweq and a flicker tweq to determine when linked hot plates are dangerous. The joint tweq, which determines when the plates are on or off, should vary between `-1` and `1`. The flicker tweq determines how often the plates are updated and should have a fairly low period. Each time the flicker triggers, the Renderer\Extra Light amount is set to the position of joint 1. If the value is greater than zero, then the meta-property HotPlateHeat is added, and it is removed if the value is less than zero.

## JunkVines

Stimulate the player when contained.

Script: | JunkVines
Inherits: | BaseScript
Messages: | Contained

The JunkEarthWebs should have both this script and JunkWebs in order to work properly. When the object is put in the inventory of the Player, it will stimulate the player by contact.

## MagicBones

Trigger when colliding with a specific object.

Script: | MagicBones
Inherits: | BaseScript
Messages: | Slain, PhysCollision
Links: | Owns

This script is meant to be used with MagicCoffin. When the object collides with its owner, it will slay itself and send BoneSlain to the owner.

## MagicCoffin

Trigger when owned objects have been slain.

Script: | MagicCoffin
Inherits: | BaseTrap
Messages: | BoneSlain
Links: | Owns

This object should be an unrendered bounding-box. Create Owns links to objects that have the MagicBones script. That script will slay each object when it collides with this one. When all of the objects have been slain, the trap will be activated.

## ModelByCount

Change the shape of an object to match it’s stack size.

Script: | ModelByCount
Inherits: | BaseScript
Messages: | Contained
Properties: | Engine Features\Stack Count, Tweq\Models

This script doesn’t work right now. Please ignore it.

## MoldSocket

...

Script: | MoldSocket
Inherits: | BaseScript
Messages: | SocketMe, UnsocketMe
Links: | ScriptParams, Owns
Properties: | Physics\Model\Attributes, Engine Features\KeySrc, Engine Features\KeyDst

...

## NearCuttyCell

Trigger for complex conversations.

Script: | NearCuttyCell
Inherits: | BaseScript
Messages: | CreatureRoomEnter, CreatureRoomExit, Obituary, Intrusion, Privacy
Links: | Population
Metaproperties: | M-NotifyRegion

This is a room script that generates the Intrusion and Privacy messages for the ConvControl script. It activates when an AI on a bad team enters or leaves the room.

Putting a lock on the controller does the same thing as this script, and can be more flexible. This script only exists to ease the transition from Thief 1.

## Prisoner

Makes the AI flee when triggered.

Script: | Prisoner
Inherits: | BaseScript
Messages: | TurnOn
Metaproperties: | M-Escapee
Signals: | Escape

Put this script on an AI that has the metaproperty M-Escapee. When a TurnOn message is sent to it, the AI will receive the signal Escape. You can also use a metaproperty that inherits from M-Escapee.

## ReallyLocked

Makes a locked object unfrobbable.

Script: | ReallyLocked
Inherits: | BaseScript
Messages: | NowLocked, NowUnlocked
Metaproperties: | FrobInert

When the object is locked it will have the FrobInert put on it. The metaproperty is removed when the object is unlocked.

## ResetLockbox

Lock the object again after it has been unlocked.

Script: | ResetLockbox
Inherits: | BaseScript
Messages: | NowUnlocked, TweqComplete
Links: | Lock, AIDoor
Properties: | Tweq\Flicker

Add the property Tweq\Flicker to the object and configure it for the time when the lock should reset. The tweq will be activated when the object is unlocked. When the tweq halts, the object is locked again. If the lock is linked to a door that is being used by an AI, then it wait some more before locking the object.

## SecureDoor

Set watch links when a door is opened.

Script: | SecureDoor
Inherits: | BaseScript
Messages: | Sim, DoorOpening, DoorClose
Links: | AIWatchObj
Parameters: | watcher(object)

AIWatchObj links will be created to this door if it changes from its original state. The links will be removed if it returns to normal. Put AI\Utility\Watch: Watch link defaults on the door to configure the links. The links will be created for all Human objects by default. Set the watcher parameter to the name of an archetype to override this.

You can make a door start in the open state by adding the property Difficulty\Close (Open) Door and leaving the flags unchecked.

## StickyVines

Create crushing vines when the object hits the player.

Script: | StickyVines
Inherits: | BaseScript
Messages: | PhysCollision
Objects: | JunkEarthWebs

Use this script on the EarthShot projectile. When it hits the Player, a JunkEarthWebs object will be put in his inventory.

JunkEarthWebs needs to have both JunkWebs and JunkVines on it.

## TrapAIWake

Wakes up inactive AI.

Script: | TrapAIWake
Inherits: | BaseTrap
Messages: | TurnOn, WakeyWakey

Use this to activate the WakeableAI script.

## TrapCreate

Reveal a contained object.

Script: | TrapCreate
Inherits: | BaseTrap
Links: | Contains

When activated, the objects contained by the trap will be revealed at its location.

It’s much better to use TrapRelease instead. This only exists for the sake of compatibility.

## TrapSecureDoor

Make an object suspicious.

Script: | TrapSecureDoor
Inherits: | BaseScript
Messages: | TurnOn, TurnOff
Links: | AIWatchObj
Properties: | Engine Features\Suspicious
Parameters: | watcher(object)

The simplest way to use this script is to add the Engine Features\Suspicious property to the object. Then the Is Suspicious flag will be just be turned on and off.

Another way creates AIWatchObj links to the object when it is turned on, and removes the links when turned off. Use the AI\Utility\Watch: Watch link defaults property to configure the links. The links will be created on all Human objects by default, or on the archetype specified in the watcher parameter.

## TrapSlayer

Slay an object using a stimulus.

Script: | TrapSlayer
Inherits: | BaseTrap
Links: | ControlDevice
Properties: | Game\Damage Model\Hit Points
Stimuli: | BashStim

This trap will slay linked objects by damaging them with a BashStim. The hit-points of the object is set to 1 first, so the damage results in death. If this isn’t done, the object won’t do some things, such as playing a schema or leaving a corpse behind.

## TrapTerminator

Destroy objects when activated.

Script: | TrapDestroy
Inherits: | BaseTrap
Links: | ControlDevice

The standard TrapDestroy script doesn’t really destroy all objects. This script, when activated, will destroy all ControlDevice linked objects, no questions asked.

## TrigOBBPlayerStuff

Trigger when the player trips the trap.

Script: | TrigOBBPlayerStuff
Inherits: | BaseTrap
Messages: | PhysEnter, PhysExit
Links: | Firer

This is an bounds trigger that is activated by the player. It trips either when the Player object walks into the bounding-box, or if something the player throws or shoots enters.

## WakeableAI

Wake up an inactive AI.

Script: | WakeableAI
Inherits: | BaseScript
Messages: | WakeyWakey
Properties: | AI\State\Current mode

Use this script on AI that won’t be part of the mission until teleported in. Set the AI\State\Current mode property to Asleep for improved performance. Then trigger the sleeping AI with the TrapAIWake script and they will wake up.

## WatchMe

Create watch links.

Script: | WatchMe
Inherits: | BaseScript
Messages: | BeginScript
Links: | AIWatchObj
Parameters: | watcher(object)

Put this script in a metaproperty. When the metaproperty is added to an object, that object will have AIWatchObj links created to it. By default, the links are created from every Human object in the mission. You can change the archetype with the watcher parameter.

## WindowShade

An animated light that changes nearby textures.

Script: | WindowShade
Inherits: | BaseTrap
Messages: | Toggle, Slain
Properties: | Renderer\Anim Light, Script\TerrReplaceOn, Script\TerrReplaceOff, Script\TerrReplaceDestroy

This is a combination of AnimLight and TrapTexture. When the light is turned on, nearby terrain will be set to the texture specified in Script\TerrReplaceOn. When turned off, Script\TerrReplaceOff is used. The object can also be slain, and then it will turn the light off and set the terrain to Script\TerrReplaceDestroy. The light can be turned back on after being slain, but the texture won’t change anymore.

The starting texture should be set to match the initial state of the light.

## SS2 Scripts

Scripts for System Shock 2. Many of these scripts are ports from Thief.

## AnimLight

Controls animated lights.

Script: | AnimLight
Inherits: | BaseTrap
Messages: | TurnOn, TurnOff, Toggle, Slain, TweqComplete, LightChange
Links: | SwitchLink, ParticleAttachement
Properties: | Renderer\Anim Light, Renderer\Self Illumination, AmbientHacked, Tweq\Flicker, Tweq\FlickerState

This is an alternative to BaseLight with features that should be familiar to Thief users. Along with TurnOn and TurnOff, the light can be changed with the Toggle message. The script also toggles the AmbientHacked property, and toggles any attached SFX. (You may want to use StdParticleGroup as well.) The light can be configured to flicker when it is turned on or off. An AnimLight can also act as a trigger.

This script doesn’t play any environmental schemas, though. If you want the object to play an activate or deactivate sound, you’ll need to add the LightSound script to the object.

Some of the Renderer\Anim Light modes do not work, including smoothly dim, smoothly brighten, and random.

## CloneContactFrob

An object that stims the user when frobbed in inventory.

Script: | CloneContactFrob
Inherits: | BaseScript
Messages: | FrobInvEnd
Properties: | Engine Features\Stack Count, Renderer\Has Refs

When this object is frobbed in the inventory, an invisible copy is made and used to stimulate the frobber by contact. The stack count of the visible object is then decremented. The life cycle of the stimulus source for the object should be configured to eventually destroy the object. Because the object is copied, any relevant properties should be set on the archetype.

This is the script that Thief uses for its healing potions.

## NotifyRegion

Send a message when an AI dies.

Script: | NotifyRegion
Inherits: | BaseScript
Messages: | Slain, Obituary
Links: | ScriptParams(Population)

When this AI is killed, a Obituary property is sent along ScriptParams links that have the data “Population”. These links are usually created by a room or OBB trigger script. Without this script, the trigger will see the AI enter, but never leave.

This script is normally put on the metaproperty M-NotifyRegion, which gets added to the AI by a trigger that needs it.

## PhysARContact

Stimulate objects that touch this one.

Script: | PhysARContact
Inherits: | BaseScript
Messages: | PhysContactCreate, PhysContactDestroy

When an object touches this one, it will receive any contact stimuli from it.

## StdParticleGroup

Control a particle SFX.

Script: | StdParticleGroup
Inherits: | BaseScript
Messages: | TurnOn, TurnOff, Die
Properties: | SFX\Particles

This script toggles particle SFX for the object. It uses a slightly different method than the standard TrapParticle script. It also handles the Die message by destroying the object.

## TraitMachineReusable

An upgrade machine that can be used more than once.

Script: | TraitMachineReusable
Inherits: | BaseScript
Messages: | FrobWorldEnd, TurnOn, TurnOff, Used
Properties: | Engine Features\Locked
Schemas: | “`Event Activate`”

This script acts like the standard TraitMachine script; but instead of permanently disabling the machine after use, it just locks it. The machine can then be used a second time if it becomes unlocked. The machine can be unlocked by sending a TurnOn message, or locked by sending TurnOff.

The lock only prevents a player from opening the trait selection overlay. If the object has already been frobbed, and the machine receives a TurnOff, then a trait can still be selected.

## TrapAddPsi

Gives psi points to the player.

Script: | TrapAddPsi
Inherits: | BaseTrap
Parameters: | psi(integer)

Increases the player’s psi points when activated, or decreases them when turned off. The psi parameter is the number of psi points to add.

## TrapCapacitor

Relay messages with a minimum time between them.

Script: | TrapCapacitor
Inherits: | BaseTrap
Properties: | Script\Delay Time

When a capacitor sends TurnOn, it will block other messages from being relayed for a period of time. If a message attempts to pass through during the discharge time, then it will be queued until the timer expires. Only the most recently received message will be sent.

This script is used when a device takes a significant amount of time to activate. A capacitor will prevent it from being turned off too quickly after it has been turned on.

## TrapConverse

Start a conversation.

Script: | TrapConverse
Inherits: | BaseTrap
Links: | AIConversationActor
Properties: | AI\Conversations\Conversation

A conversation is an elaborate set of pseudo-scripts. They are used a lot in Thief, but not at all in System Shock 2. I can’t imagine why.

A conversation can involve up to six different AI, known as actors. Create AIConversationActor links from the conversation trap to the actors, and set the data for each link to the actor number for that AI, starting with 1. (It’s easy to forget this, since the default value is 0.) Add the property AI\Conversations\Conversation to the trap and set the actions you want to occur. Each step of the conversation is a set of actions that will be taken. The next step doesn’t occur until the previous step has completed.

The normal AI behavior can sometimes interfere with a conversation. It helps to add the metaproperty Silent to the actors in a conversation.

I could say more, but I’m afraid that I might say something wrong. Conversations are damned tricky and I don’t have very good luck with them.

## TrapKeypad

Relay if the correct code is entered in a keypad.

Script: | TrapKeypad
Inherits: | BaseTrap
Messages: | KeypadDone
Links: | ScriptParams(ErrorOutput)
Properties: | Script\Keypad Code

When this trap is activated, it will prompt for a code to be entered. The correct code will cause TurnOn to be relayed. Entering the wrong code sends TurnOn along ScriptParams links that have the data set to “ErrorOutput”. Of course, the code is specified in the Script\Keypad Code property.

## TrapNanites

Relay if the player has enough credits.

Script: | TrapNanites
Inherits: | BaseTrap
Links: | ScriptParams(ErrorOutput)
Parameters: | nanites(integer)

This is a relay that will add nanites to the player when turned on. Turning off the trap, or specifying a negative value for nanites, will deduct the amount from the player. If there aren’t enough nanites to deduct, then a message is displayed, and a TurnOn message is sent along ScriptParams links that have the data “ErrorOutput”. Adding nanites will always succeed. The trap can have a revert timer set and the player will only be charged once.

## TrapPatrol

Activate a patrol route on linked AI.

Script: | TrapPatrol
Inherits: | BaseTrap
Links: | SwitchLink
Properties: | AI\Ability Settings\Patrol: Does patrol

This trap enables or disables patrolling of AI. The AI to control are linked from the trap with SwitchLink.

## TrapRequireAll

Trigger if all the controllers are turned on.

Script: | TrapRequireAll
Inherits: | BaseTrap
Links: | ScriptParams(Require), SwitchLink

This script monitors a number of triggers. When they have all been turned on, the trap relays TurnOn. TurnOff is sent if any of the triggers turns off. The triggers that have been turned on are tracked using ScriptParams links with the data set to “Require”. The triggers must all link to this trap using SwitchLink.

## TrapRequireAny

Trigger if any of the controllers is turned on.

Script: | TrapRequireAny
Inherits: | BaseTrap
Links: | ScriptParams(Require)

This script monitors a number of triggers and sends TurnOn when at least one of them is turned on. TurnOff is sent when all the triggers are turned off. The triggers that have been turned on are tracked using ScriptParams links with the data set to “Require”. Unlike TrapRequireAll, the triggers can communicate with this trap over links other than SwitchLink.

## TrapRevert

A relay that will automatically turn itself off.

Script: | TrapRevert
Inherits: | BaseTrap

This is a standard trap that just relays messages. The revert timer will function for TurnOff messages, though, as well as TurnOn.

## TrapTexture

Change the texture of terrain.

Script: | TrapTexture
Inherits: | BaseTrap
Properties: | Engine Features\Retexture Radius
Parameters: | terrreplaceon(string), terrreplaceoff(string)

This trap controls the texture of nearby terrain. Set the parameters to the path to the texture resource for when the trap is turned on and when it is turned off. Any cells within the retexture radius will have their polygons swapped between the old and new textures. You need to have the textures initially set to the same state as the trap. Changing textures won’t work if the new texture isn’t also loaded into the mission. The default value of Engine Features\Retexture Radius is zero, so you must set the property for this script to function.

## TrigAIAlert

Trigger when an AI is alerted.

Script: | TrigAIAlert
Inherits: | BaseScript
Messages: | Alertness, TurnOn
Links: | SwitchLink

When an AI goes to alert level 3, a TurnOn will be sent along SwitchLink links.

## TrigContained

Trigger when an object goes into or out of a container.

Script: | TrigContained
Inherits: | BaseTrap
Messages: | Contained

This script sends TurnOn when an object is picked up or dropped.

## TrigFlicker

A repeating trigger.

Script: | TrigFlicker
Inherits: | BaseTrap
Messages: | TweqComplete
Properties: | Tweq\Flicker, Tweq\FlickerState

Flicker triggers send alternating TurnOn and TurnOff messages controlled by a flicker tweq. The tweq is turned on and off when the trap is activated or deactivated. The Tweq\Flicker property should be configured to Continue and have the Scripts flag turned on.

## TrigInvFrob

Trigger when an object is frobbed in the inventory

Script: | TrigInvFrob
Inherits: | BaseTrap
Messages: | FrobInvEnd

Activates when the object is frobbed while in the inventory.

## TrigPPlate

Trigger when a pressure plate is depressed.

Script: | TrigPPlate
Inherits: | BaseScript
Messages: | PressurePlateActive, PressurePlateInactive
Links: | SwitchLink
Properties: | Physics\Misc\Pressure Plate

Pressure plates are a specialized type of terrain-like object. The object must have an OBB physics model and the property Physics\Misc\Pressure Plate. When sufficient weight is placed atop the object, it will move down. This script is activated by that movement. TurnOn is relayed along SwitchLink links when the pressure plate is completely lowered, and TurnOff is relayed when it raises up again.

## TrigPPlateImmed

Trigger when a pressure plate begins moving.

Script: | TrigPPlateImmed
Inherits: | BaseScript
Messages: | PressurePlateActivating, PressurePlateDeactivating
Links: | SwitchLink
Properties: | Physics\Misc\Pressure Plate

This script is activated by a pressure plate object, like TrigPPlate. TurnOn is relayed when the pressure plate begins moving down, and TurnOff is relayed when it begins moving upwards.

## TrigRoomCreature

Trigger when an AI enters a room.

Script: | TrigRoomCreature
Inherits: | BaseScript
Messages: | CreatureRoomEnter, CreatureRoomExit, PlayerRoomEnter, PlayerRoomExit, Obituary
Links: | SwitchLink, ScriptParams(Population)
Metaproperties: | M-NotifyRegion

This is a trigger for rooms. It is activated when an AI enters the room. The trigger will deactivate after all AI have left the room. The AI inside the room are tracked using ScriptParams links that have the data set to “Population”. You should create a metaproperty named M-NotifyRegion that contains the script NotifyRegion. The trigger will add this metaproperty to the AI it is tracking so it can get the Obituary message if the AI were to be slain inside the room.

## TrigRoomDelivery

Trigger when a player carries an object into a room.

Script: | TrigRoomDelivery
Inherits: | TrigRoomObject
Messages: | Contained

Put this script on an object and it will trigger when it is carried into a room by one of the players. The trigger turns off if the object is dropped, even inside a target room. The object is linked to the target rooms with ScriptParams links that have the data set to “Route”.

## TrigRoomDeposit

Trigger when the object is dropped in a room.

Script: | TrigRoomDeposit
Inherits: | TrigRoomObject
Messages: | Contained

Put this script on an object and it will trigger when dropped in a specific room. The trigger turns off if the object leaves the room, or is picked up again. The object is linked to the target rooms with ScriptParams links that have the data set to “Route”.

## TrigRoomObject

Trigger when an object enters a room.

Script: | TrigRoomObject
Inherits: | BaseScript
Messages: | ObjRoomTransit
Links: | SwitchLink, ScriptParams(Route)

Put this script on an object and it will trigger when entering a target room. You can specify any number of target rooms using ScriptParams links that have the data set to “Route”.

## TrigRoomPlayerTrans

Trigger when moving between two rooms.

Script: | TrigRoomPlayerTrans
Inherits: | BaseScript
Messages: | PlayerRoomEnter, PlayerRoomExit
Links: | SwitchLink, ScriptParams(Route)

Create a ScriptParams link between two rooms. Give the link the data “Route”. When a player moves from the room that’s the source of the link into the room that’s the destination of the link, then the trigger will send TurnOn. Moving in the opposite direction sends TurnOff.

## TrigRoomPopChange

Trigger when someone enters or exits a room.

Script: | TrigRoomPopChange
Inherits: | TrigRoomCreature
Messages: | CreatureRoomEnter, CreatureRoomExit, PlayerRoomEnter, PlayerRoomExit, Obituary

This script is for room objects. It sends a TurnOn message anytime an AI or the Player enters or leaves the room.

## TrigUnlock

Trigger when the object is locked or unlocked.

Script: | TrigUnlock
Inherits: | BaseScript
Messages: | NowLocked, NowUnlocked
Links: | SwitchLink

Sends a TurnOn message when the object is unlocked. TurnOff is sent when it is locked.

## TrigWorldFrob

Trigger when frobbed in the world.

Script: | TrigWorldFrob
Inherits: | BaseTrap
Messages: | FrobWorldEnd

This trigger activates when the object is frobbed in the world.

# Programmer’s Reference

This section is for OSM developers.

## Chapter 1. Source Code Overview

The source code for Public Scripts is included with the software. Under the terms of the GNU General Public License, you may use this source code to create your own software. Or you can just study it for informational purposes.

The source code that makes up the scripts is actually four somewhat independent packages.

Public Scripts: | The scripts themselves. This is the core of the OSM; everything else is supplemental.
ScriptLib Library: | A library of functions useful in any script project.
lg Library: | The core headers and support code required to build an OSM.
Dark Hook 2: | A DLL that allows script modules to register hook functions with the game.

## Public Scripts

The Public Scripts are built with a modular design that allows a single set of source files to be compiled for all three games. The classes are compact enough to be self-documenting. And, by virtue of the pre-processor, only three extra lines of code are needed to add a new script.

## ScriptLib

There are many simple procedures that scripts use often enough to justify creating a library out of.

## GetObjectParams

Get the contents of the design note.

`char* GetObjectParams(`iObject`)`;
int iObject;

Retrieves the contents of the design note for a particular object. The return value, if non-`NULL`, will have been allocated by g_pMalloc and should be free’d by the same.

## GetObjectParamString

Get the value of a design note parameter.

`char* GetObjectParamString(`iObject, pszParam`)`;
int iObject;
const char* pszParam;

`int GetObjectParamInt(`iObject, pszParam`)`;
int iObject;
const char* pszParam;

`float GetObjectParamFloat(`iObject, pszParam`)`;
int iObject;
const char* pszParam;

`bool GetObjectParamBool(`iObject, pszParam`)`;
int iObject;
const char* pszParam;

`int GetObjectParamObject(`iObject, pszParam`)`;
int iObject;
const char* pszParam;

`int GetObjectParamTime(`iObject, pszParam`)`;
int iObject;
const char* pszParam;

Retrieves a design note parameter for a particular object. If the parameter doesn’t exist, the return value is `NULL` or `0`. For `GetObjectParamString`, a non-`NULL` value will have been allocated by g_pMalloc.

## lg Library

This library contains the interface definitions required for scripts to interact with the game. The most significant interfaces are found in scrservices.h.

## Dark Hook 2

Scripts can register to receive notification of changes to an object, but this requires a callback function. OSM modules are too volatile for this. The Dark Hook 2 module can be loaded to provide the necessary functions. Scripts are then notified using script messages.

## Chapter 2. Documentation Source

The documentation files for Public Scripts (what you are now reading) are generated from a modified DocBook XML source. The root of the document is in PublicScripts.xml and other fragments are in PublicScripts-common.xml, PublicScripts-dev.xml, PublicScripts-legacy.xml, PublicScripts-t1.xml, PublicScripts-t2.xml, and PublicScripts-ss2.xml. All the files use UTF-8 encoding and CRLF line-endings.

## Revision History

-     2.0 - The “Machina Populi” release.
         Sometime in the future.

-     Beta 1 - 2006-12-30
         Adjustments for compatibility with MSVC.
         Drop FrobSounds, StopHere, and TrigBraindead from T1. They’re already in Thief Gold.
         TrapFlipFlop initializes on BeginScript.
         Add IntrinsicText. Affects IntrinsicCover and IntrinsicPlaque.

-     Test 4 - 2006-08-12
          Add TrapRequireOne, TrapRequireOneOnly.
          SS2: TrapRequirement is gone. Requirements are handled by an abstract class that can be used in any game.
          Population tracking for OBB and Room triggers moved into a common abstract class.
          TrigOBBSpec: Trigger on any submodel. Use population tracking to avoid double-triggering.
          utils.cpp: But in FixupScriptParamsHack.
          TrapMissionQVar: SS2 can use this script to store mission-specific qvars.
          Change how TrapRequireOne and TrapRequireOneOnly deal with trap control flags so it makes more sense.
          T2: HotPlateControl didn’t set the meta-property at the right times.

-     Test 3 - 2006-02-15
         Still working at it.
         Haven’t really been keeping track of changes, I’ll do a better job from now on... maybe.
         First appearance of this snazzy XML documentation.

-     Test 2 - 2005-11-28
         Some further refinements. I think I only showed this to NamelessVoice.

-     Test 1 - 2005-06-29
         A first glimpse at Public Scripts.