[TOC] [Prev] [Next]

INF Files

INF files control the dynamic workings of a level, turning static sectors and walls into doors, switches, elevators, rotating fans, forcefields, and so on. They are text files written in "The INF language". Although not a true programming or scripting language, INF can be used to create scripted events in a level: for example, mission completion, conversations between characters, and opening access to new parts of the level as objectives are completed.

INFs accept C like /* */ comments.

They are made up of item definitions, which are linked to the corresponding LEV file


Contents

  1. INF file format
  2. INF item overview
  3. item: level
  4. Elevators
  5. Triggers
  6. Teleporter chute
  7. INF properties
  8. INF messages
  9. Special INF functions
  10. INF functions from DARK.EXE
Details

INF File Format

Here is the header of the INF file:

|  INF 1.0
|  LEVELNAME SECBASE   
|
|  items 2

INF File version and level name, followed by total number of items in the file. Don't forget to change this value when you add or remove items in an INF.

Then follow the items:

Sector Item.
|  item: sector  name: secname   
|    seq
|     ........
|    seqend
 

Wall Item.
|  item: sector  name: secname  num: #wallnum   
|    seq
|     ........
|    seqend

etc.

See also item: level

Each item follows the same format. The "code" for each item is enclosed within the seq and seqend statements.

Note:
More than one class statement is allowed per item.

Back to top

INF item overview

Each sector or wall item will have one or more classes. There are 3 types of classes:

elevators They modify sectors or their walls
triggers When triggered, they send a message to their client(s)
teleporter chute A very special item used to "fall" to another sector

Each class will have several properties that can be customized to change how the class functions.

Messages can be sent around a level to modify sectors, walls, and INF items.

There are a few special functions that can be executed: create an adjoin:, page: a sound, and display a text: message.

See also some new INF functions that weren't used in the original levels, but were found in DARK.EXE

Back to top

INF item: level

This is used to play an ambient sound in the entire level.

This is never successfully used in the original 14 levels. There is, however, a failed attempt in EXECUTOR.INF.

usage:
| item: level
|  seq
|     amb_sound: [voc file] [num] [num]
|  seqend

The meaning of the 2 nums are unknown. Including them seems to stop the sound from playing.

Back to top

Class: Elevators

Elevators make sectors (or their walls) dynamic. They can be used to create lifts, platforms, doors, conveyor belts, flowing water etc. They are also used for "dummy" (i.e. non-accessible) elevators for level control and scripting purposes.

Elevators will usually have stops, which are different values the elevator can arrive at.

Elevators may also have slaves copying their actions.

Here are the elevator classes:

elevator change_light
elevator basic
elevator inv
elevator move_floor
elevator move_ceiling
elevator move_fc
elevator scroll_floor
elevator scroll_ceiling
elevator move_offset
elevator basic_auto
elevator change_wall_light
elevator morph_move1
elevator morph_move2
elevator morph_spin1
elevator morph_spin2
elevator move_wall
elevator rotate_wall
elevator scroll_wall
elevator door
elevator door_mid
elevator door_inv

stop:

A stop is a value that an elevator can arrive at. The meaning of the value varies depending on the class of elevator, and can be floor altitude, ceiling altitude, ambient light, degrees of rotation etc. Stops are used in dummy elevators for level scripting control. Elevators can send a message, page a sound, or create an adjoin upon arriving at a stop.

Note: Elevators can have any number of stops, including zero. If no stops are given, the elevator will be continuously moving, so long as its MASTER is on. This is used for continuously scrolling (eg. to create a conveyor belt) and rotating elevators, but should not be used for "elevator move_floor" and others !!!

Note: Door elevators should NOT be given stops. They will have automatic stops set depending on the altitudes of the floor and ceiling of their sector.

Note: that altitudes in INF are expressed in normal fashion (opposite to LEV and O files) -- positive values are "up" and negative values are "down".


usage:
| stop: [value1] [value2]

The first value can be given in three ways:

| [num]		absolute stop
| @[num]	relative stop
| [sectorname]	equal the value of the sector [sectorname]
					

The second value can be given in 4 ways:

| [time]	time in seconds that elevator remains at stop. Can be non-integer value.
| hold		elevator will remain at stop until triggered to move again
| terminate	elevator will stay at the stop permanently
| complete	mission will be complete when elev arrives at this stop

The second (time) value can be omitted, in which case the elevator will remain at the stop for a default amount of time.

When an elevator arrives at a "complete" stop, the current mission will be complete. The mission complete message will be displayed on the screen, and the player will be allowed to press ESC and advance to the next mission.

slave:

A slave of an elevator will follow whatever the elevator does does. However, if relative stops are used, the slave may not necessarily have the exact same actions. For example, a sector with "elevator move_floor" may have a floor altitude of 0 and a slave of it may have a floor alt of 4. When the elevator moves to "stop: @5" the slave will move to altitude 9.

usage:
| slave: [slave sectorname]

Back to top

Class: Triggers

Triggers send a message to a client sector when triggered. They can be used to create switches, tripwires etc. Triggers can also be used to display text.

A trigger can be either a sector or a wall.

Note: if no message is specified, then the default message (m_trigger) will be sent to the client(s).

Here are the trigger classes:
trigger standard
trigger
trigger switch1
trigger single
trigger toggle

client:

Used with triggers, client defines which sector(s) a message is sent to when the trigger is triggered. A trigger may have one or more clients. Every trigger should have at least one client, unless it is a trigger used to display TEXT.

usage:
| client: [client sectorname]

Back to top

Class: Teleporter Chute

Teleporter chutes are a special class of their own. Their function is to teleport the player directly up or down (usually down) to a target sector.

Dark Forces teleporter chutes are not deliberate teleporters like in DOOM. They are usually not intended to be noticed by the player, and are intended to make it look like the player has just fallen through a chute into a layer below, for example, in the Robotics Facility where you fall through the fan into the gas room.

Teleporter chutes create an illusion of two rooms that are vertically connected.

Teleporter chutes send you directly up or down, without changing the player's X-Z (horizontal) position. Therefore the target sector must occupy the same X-Z space of the teleporter chute, or the player may be teleported into the "void" outside of a sector.

usage:
| class: teleporter chute
| target: [target sectorname]

Back to top

INF Properties

Properties are set for elevators and triggers, and determine their behaviour.

If an INF item has more than one class, each class is followed by its properties:

seq
  class elevator eeeee                 
    speed: xx
    event_mask: xx
    master: xx
    .....

  class elevator eeeee
    speed: xx
    event_mask: xx
    master: xx
    .....

  trigger tttttt
    event_mask: xx
    .....
seqend

List of properties

master:
event_mask:
event:
entity_mask:
speed:
start:
center:
angle:
key:
flags:
sound:
object_mask:

Back to top

INF Messages

Messages are sent from triggers when they are triggered and elevators when they arrive at stops. They are sent to other triggers and elevators, and in some cases just regular sectors and lines (except message: lights, which is sent to the system). They do various things to their recipients.

Messages all have these general syntax:

sent from an elevator
| message: [stop number] [receiver] [message] [parameters] [event (optional)]

sent from a trigger
| client: [receiver]
| message: [message] [parameters] [event (optional)]

[receiver]  is the receiver of a message. Can be one of the following:
	[sectorname] 				receiver is a sector 
	[sectorname([wallnum])] 		receiver is a wall
	SYSTEM 					receiver is the SYSTEM (message: lights only)
	
[parameters]	are parameters specific to the type of message.

[event (optional)]	specifies the custom event; used to send a message selectively to multi-class items
				

Here are the messages:

m_trigger
goto_stop
next_stop
prev_stop
master_on
master_off
clear_bits
set_bits
complete
done
wakeup
lights

Remember that when you look at an INF file and you see something like :

| class: elevator eeeee
|  stop: 0 hold
|   message: 0 mmmmm
|  stop: 1 5
|   message: 1 mmmmm
|  stop: 2 hold
|   message: 2 mmmmm

...the grouping of messages after their stops is only a convention, and you could group all the messages in one place and in any order. The following would work the same:
| class: elevator eeeee
|  stop: 0 hold
|  stop: 1 5
|  stop: 2 hold
|   message: 0 mmmmm
|   message: 1 mmmmm
|   message: 2 mmmmm

Important : if you add a stop, you have to renumber !

Notes:

Back to top

INF Special Functions

adjoin:

Adjoins a line to another line when an elevator arrives at a stop, removing any adjoins it had with a previous line. This is required if you need a line to remove its adjoin with one line and adjoin with another line midway through a level. "Adjoin" is placed in an elevator's code block.

For example, in level 6 (detention center), you may notice that the 2 main lifts have a door on each layer adjoined to it on the same line. Since a line cannot be adjoined to more than one other line at once, the following occurs: midway through moving up between 2 layers, the elevator move_floor arrives at a stop which it remains at for 0 seconds. At this stop, a line of the lift sector is adjoined to a line of the door sector on the layer above, at the same time removing its adjoin with a line of the door sector on the layer below. The lift's doors all appear to be directly on top of each other.

usage:
| adjoin: [stopnum] [sector1] [line1] [sector2] [line2]


page:

Plays a sound effect when an elevator arrives at a stop. "Page:" is placed in an elevator's code block.

usage:
| page: [stopnum] [VOC file]


text:

Displays a text message from TEXT.MSG when a trigger is triggered. "Text:" is placed in a trigger's code block.

usage:
| text: [text number in text.msg] 

texture:

[by Anthony Hall]

The texture: command's format is like this:

texture: [stopnum] [flag] [donor]

This command will copy the texturing from one specified sector to another one. It must be used in the INF entry of the sector that will be changed. [donor] is the sector to copy a texture from. The flag tells whether to copy ceiling to ceiling texture or floor to floor. If the flag starts with a letter then ceiling textures will be used. If it's a number then floors will be used.

I haven't been able to get it to work with walls or in trigger INF entries though.

Back to top

New INF Functions from Dark.exe

These are INF functions found in DARK.EXE but were not used in the original 14 levels.

Elevators:
elevator move_offset
elevator basic_auto
elevator move_wall
elevator door_inv
Properties:
object_mask:
Special Functions:
texture:

Here are some INF keywords that were found in DARK.EXE but as yet are not understood. We would appreciate it if people could help work out these as they may be usable!

stop_y:
trigger_action:
condition:
enclosed
mid
entity_enter
move:

Back to top

Elevator Classes Descriptions

elevator change_light

Changes the AMBIENT LIGHT of a sector.

Stop values are sector AMBIENT (as found in the LEV file) and can be from 0 to 31.

elevator basic

Changes FLOOR ALTITUDE of a sector.

Stop values are the altitude of the floor.

elevator inv

Changes the CEILING ALTITUDE of a sector. Often used for making doors (as you can set Smart Object Reactions).

Stop values are the altitude of the ceiling.

elevator move_floor

Changes the FLOOR ALTITUDE of a sector. The difference from "elevator basic" is that the smart object flag does not affect this elevator.

Stop values are the altitude of the floor.

elevator move_ceiling

Changes the CEILING ALTITUDE of a sector. The difference from "elevator inv" is that the smart object flag does not affect this elevator.

Stop values are the altitude of the ceiling.

elevator move_fc

Changes both the FLOOR ALTITUDE and CEILING ALTITUDE of a sector, i.e. the floor and ceiling will move up and down together.

Stop values are the altitude of the floor.

elevator scroll_floor

Scrolls the floor texture of a sector. Player moves with the floor texture by default, but see the FLAGS property.

Stop values are distances in pixels ( x by 8 to get distances in level geometry units).

elevator scroll_ceiling

Scrolls the ceiling texture of a sector.

Stop values are distances in pixels ( x by 8 to get distances in level geometry units).

elevator move_offset

Changes the SECOND ALTITUDE of a sector.

Stop values are second altitude.

elevator basic_auto

Changes the FLOOR ALTITUDE of a sector, but returns to altitude 0 after cycling through all its stops. From there, its event needs to be triggered twice to move it to its first stop again. Otherwise, seems to be the same as elevator_basic.

Stop values are floor altitude.

elevator change_wall_light

Changes the LIGHT of any walls in the sector with flag 1 bit 8 (allow change wall light), i.e. the relative light level of a wall to the sector will change.

Stops values are wall light.

elevator morph_move1

Translates the VERTEX positions of any walls in the sector with flag 1 bit 32 (wall morph with sector). The entire wall will translate on the X-Z plane.

If the walls are adjoined, their mirrors also need to move so should also be set with flag 1 bit 32.

The PLAYER will by default not move with the walls. (but see the FLAGS property).

Stop values are distances on the X-Z (horizontal) plane relative to the starting location of the wall.

elevator morph_move2

Same as elevator morph_move1 except the PLAYER will by default move relative to the walls if it is in the sector (but see the FLAGS property).

elevator morph_spin1

Rotates the VERTEX positions of any walls in the sector with flag 1 bit 32 (wall morph with sector). The entire wall will rotate on the X-Z plane.

If the walls are adjoined, their mirrors also need to move so should also be set with flag 1 bit 32.

The PLAYER will by default not spin with the walls (but see the FLAGS property).

Stop values are angles in degrees.

elevator morph_spin2

Same as elevator morph_spin1 except the PLAYER will spin relative to the walls if it is in the sector (but see the FLAGS property).

elevator move_wall

This is the same as elevator morph_move1 except that it has a default event_mask of 0.

elevator rotate_wall

This is the same as elevator morph_spin1 except that it has a default event_mask of 0.

elevator scroll_wall

Scrolls texture(s) of any walls in the sector with flag 1 bit 64/128/256/512 (allow scroll mid/top/bot/sign texture). Stop values are distances in pixels ( x by 8 to get distances in level geometry units)

elevator door

Instant door. Note, that it is easier to just use flag 1 bit 2 on a sector for an instant door. Elevator door is only really needed if you want to alter properties, for example, create a key door.

Stops and event_mask are set automatically - just make sure that the ceiling altitude of the sector is when the door is OPEN.

elevator door_mid

Instant 2 part door (opens upwards AND downwards). Information for the top and bottom parts are specified individually (so if you want to set a key, you have to set it to both halves of the door).

i.e.
| class: elevator door_mid
|  addon: 0
|  [info for the top part]
|  addon: 1
|  [info for the bottom part]

Stops and event_mask are set automatically - just make sure the floor and ceiling altitudes of the sector are of the door when it is OPEN.

elevator door_inv

A door that opens downwards. Otherwise, the same as any other door elevator.

Stops and event_mask are set automatically - just make sure that the floor altitude of the sector is when the door is OPEN.


Trigger Classes Descriptions

trigger standard

This can be applied to a sector (entering, leaving, nudging it etc.) or a line (crossing, nudging it etc.). Can't be used with switches, or you get a single vertical line where the sign should be.

trigger

Appears to behave exactly the same as trigger standard, possibly because trigger standard is the default.

trigger switch1

This is used specifically for switches. Remember, the wall containing the switch should have a SIGN TX which is a switch texture. When the switch is pressed, the first texture will change to the second texture in the multiple BM. The second texture can't be pressed - a message: done must be sent to change the switch back to its first state. This can be done as many times as you like.

trigger single

This is a trigger that is used with switches. The switch can only be pressed ONCE. Once the switch is on its second texture, it will remain there even if a "message: done" is sent.

trigger toggle

This is a trigger that is used with switches. The switch can be pressed while showing either texture, so there's no need for "message: done".


Properties Descriptions

master:

Determines whether an elevator or trigger is active or inactive. If master is off, the elevator or trigger will not respond to the player or other entities. An elevator or trigger with master off will not respond to messages either.

usage:

| master: on|off

Default:
| master: on

event_mask:

Determines what event(s) will operate an elevator or trigger. The event, when it occurs, will move an elevator to its next stop, or activate a trigger. If event_mask is 0, an elevator can only be controlled by messages sent from other INF items; it will not respond directly to the player.

event_mask values
1 Cross line from front side
2 Cross line from back side
4 Enter sector
8 Leave sector
16 Nudge line from front side / Nudge sector from inside
32 Nudge line from back side / Nudge sector from outside
64 Explosion (eg. thermal detonator or mortar)
256 Shoot or punch line (see entity_mask )
512 Land on floor of sector

(The above are bit values, so are added up when more than one are needed.)

* or -1 All bits set
1024 or higher Activated by custom event values, see event:

usage:
| event_mask: [value]

See Defaults Below

event_mask defaults

elevs basic, inv, basic_auto
| event_mask: 52
elevs morph_move1, morph_move2, morph_spin1, morph_spin2
| event_mask: 60
other elevators
| event_mask: 0
all triggers
| event_mask: *

event:

Creates a custom event value for a trigger. The trigger will then only affect an elevator class with this event value set in its event_mask. The custom value should be a bit value (i.e. a power of 2) so that it can be added with the other custom and preset bits (this works fine). LEC always uses 65536 onwards so this seems advisable. However, it seems that you do not HAVE to use a bit value because in EXECUTOR.INF LEC uses 2621444 (note the extra 4) and it works OK. But this is not recommended.

Event: is needed with multi-class elevators or triggers where each class is controlled by a separate trigger. For example in Testbase (level 4), the sector called "Corecat" (spins around the Phrik metal) is two classes of elevator - elevator move_fc and elevator morph_spin2. Two switches control these classes individually. If the "event" property was not used, both switches would trigger both classes of elevator. Utilising the event property, it is made possible to isolate the two classes to different switches.

usage:
| event: [value]

entity_mask:

Defines the entity type that triggers a trigger. By changing this, you can create a shootable switch, or a trigger that will respond to enemies but not the player.

entity_mask values
1Enemy
8 Weapon
2147483648Player

(The above are bit values, so are added up when more than one are needed.)

* or -1 All bits set

Note: Enemies and weapons (laser bolts, rockets etc.) can enter and leave sectors and cross lines just like the PLAYER, but can't nudge or land on the floor. i.e. you can use entity_mask values 1 and 8 with event_mask values 1, 2, 4 and 8 but NOT with 16, 32 and 512.

usage:
| entity_mask: [value]

Default:
| entity_mask: 2147483648

speed:

Determines the speed that an elevator moves between stops, in stop units per second. If speed: 0 is set the elevator will move between stops instantaneously.

usage:
| speed: [value]

Default:
Different for each type of elevator.

start:

Determines which stop an elevator starts at, when the level loads.

usage:
| start: [stopnum]

Default:
| start: 0

center:

Used with rotating elevators, center defines the coordinates of the center of revolution.

usage:
| center: [x coord] [z coord]

Default:
| center: 0 0

angle:

Used with texture-scrolling or horizontally moving elevators, angle defines the direction in which the texture will scroll or the sector will move. For scrolling walls, angle: 0 is down. For horizontally moving and scrolling elevators, angle: 0 is north.

usage:
| angle: [value in degrees]

Default:
| angle: 0

key:

Defines which key the player must have to activate the elevator. Key is optional, of course.

usage:
| key: red|blue|yellow

flags:

Determines how the player moves with a morph_move, morph_spin or a scroll_floor elevator.

flag values
1 Move on floor
2Move on 2nd altitude

These are bit values, so can be added (3) for moving on both the floor AND 2nd alt.

2nd altitude applies for both negative ("water") and positive ("bridges") 2nd altitudes.

This property appears to affect enemies and items when used with elevator morph_xxxx, but not with scroll_floor. So enemies cannot be moved by a conveyor belt in Dark Forces.

Note: In FUELSTAT.INF you may find "flags: 7". This suggests that there is a value for 4 as well but its purpose is unknown.

Note: In some places in the original levels, flags is set on vertically moving elevators like move_floor and move_fc. I'm not sure whether this is a mistake, or if flags do something different here.

usage:
| flags: [value]

flag defaults
elevs scroll_floor, morph_move2, morph_spin2
| flags: 3

elevs scroll_ceiling, morph_move1, morph_spin1, move_wall, rotate_wall
| flags: 0

Note: all slaves will have flags set to 0.

sound:

Sets the sound effects of the elevator or trigger. Elevators have 3 sound effects - leaving a stop (1), moving between stops (2), and arriving at a stop (3). Triggers only have one sound - when triggered.

usage (elevators):
| sound: [sound value (1, 2 or 3)] [VOC file]

usage (triggers):
| sound: [VOC file]

Note: Setting "0" in place of [VOC file] makes the sound effect silent.

Also See Defaults Below

sound defaults
elevs change_light, change_wall_light, scroll_floor, scroll_ceiling,  and scroll_wall
| sound: 1 0
| sound: 2 0
| sound: 3 0

elevs move_floor, move_fc, basic, basic_auto, change_offset,  door_inv and bottom half
of door_mid
| sound: 1 elev2-1.voc
| sound: 2 elev2-2.voc
| sound: 3 elev2-3.voc

elevs move_ceiling, inv, morph_move1, morph_move2, morph_spin1,  morph_spin2, move_wall,
rotate_wall and top half of door_mid
| sound: 1 door2-1.voc
| sound: 2 door2-2.voc
| sound: 3 door2-3.voc

elevator door
| sound: 1 door.voc
| sound: 2 0
| sound: 3 0

trigger standard
| sound: 0

triggers switch1, single and toggle
| sound: switch3.voc

object_mask:

This seems to work like event_mask when used with an elevator, and like entity_mask when used with a trigger. It is not used in the original levels.


Messages Descriptions

m_trigger

Triggers an elevator or trigger (no matter what its event_mask value is). An elevator will be moved to its next stop, and a trigger will be triggered.

Sent from an elevator.

Sent to a line trigger or sector trigger or an elevator.

Parameters:

[event value] optional -- the message will only be sent to the class with this event value set in its event_mask

goto_stop

Sends an elevator to a specified stop.

Sent from a trigger or an elevator.

Sent to an elevator.

Parameters:

[num] Stop number to send elevator to.

next_stop

Sends an elevator to its next stop.

Sent from an elevator or trigger.

Sent to an elevator.

Parameters:

[event value] optional -- the message will only be sent to the class with this event value set in its event_mask

prev_stop

Sends an elevator to its previous stop.

Sent from an elevator or trigger.

Sent to an elevator.

Parameters:

[event value] optional -- the message will only be sent to the class with this event value set in its event_mask

master_on

Turns an elevator's or trigger's master on.
This message also turns on all generators in the recipient sector with "master: off" set in the .O file.

Sent from an elevator or trigger.

Sent to an elevator or trigger (or a normal sector with generators in it).

Parameters:

[event value] optional -- the message will only be sent to the class with this event value set in its event_mask

master_off

Turns an elevator's or trigger's master off.

Sent from an elevator or trigger.

Sent to an elevator or trigger.

Parameters:

[event value] optional -- the message will only be sent to the class with this event value set in its event_mask

clear_bits

Clears specified flag bits from a wall or sector. To clear more than one bit, add the bit values up that you want cleared.

Sent from a trigger or elevator.

Sent to a sector or wall.

Parameters:

[flagnum] -- flag number (1, 2 or 3)
[bitnum] -- bit value to clear

set_bits

Sets specified flag bits to a sector or wall. To set more than one bit, add up the bit values that you want to be set.

Sent from a trigger or elevator.

Sent to a sector or wall.

Parameters:

[flagnum] -- flag number (1, 2 or 3)
[bitnum] -- bit value to set

complete

Tells the GOL file that a trigger goal has been completed, updating the objective screen. Also moves recipient elevator to its next stop.

Sent from a trigger or an elevator.

Sent to an elevator (preferably to your "complete" elevator as it will also be moved one stop closer to its complete stop).

Parameters:

[num] refers to the "TRIG: [num]" in the GOL file. The corresponding goal in your PDA will then be shown to be complete (if your ANIM is done correctly, that is!!!)

done

Puts a switch on its first texture - it can be pressed again (UNLESS it is a trigger single).

Sent from an elevator.

Sent to a line trigger.

Parameters: none

wakeup

VUEs with "PAUSE: TRUE" will be played through once when this message is sent to the sector containing the 3DO object.

Sent from an elevator.

Sent to a sector.

Parameters: none

lights

Toggles the AMBIENT light of ALL sectors in the level between their original setting and the value of sector flag 3. Using sector flag 3 bits 1, 2, 4, 8, and 16 it is possible to make any AMBIENT level from 0 to 31.

Sent from an elevator or trigger.

Sent to the SYSTEM (treat it like a sector with name "system", but make sure there are NO actual sectors called "system" anywhere in your level!

Parameters: none