Files
questshock/modding/ss-specs/levelObjects/Actions.md
T

30 KiB

Actions

Level traps and various fixtures (buttons and the like) make use of actions that perform some state change and/or give some indication to the player. They are essentially what make a level (and the game in total) come to life.

Actions can be triggered by various sources. They may have conditions that first have to be met before the action is actually performed. The type of the action determines how to interpret the details (parameters) of the action.

Quest Value Key

Some actions make use of quest value keys, which are used to either resolve a raw value, or a value from the game variables ("quest values").

  • If bit 0x1000 is set in the key, the current integer game variable value of index key & 0x0FFF is referenced.
  • If bit 0x2000 is set in the key, the current boolean game variable value of index key & 0x0FFF is referenced.
  • For resolving values, if the key is less than 0x1000, then the resulting value is the value key itself.

Action Data

Action Data (22 bytes)

0000  byte       Action type
0001  byte       Use quota
0002  [4]byte    Condition
0006  [16]byte   Action details

The Use quota indicates how often more this action can be executed. 0 means endless. The value is only decremented if it is not zero and the condition was met. If the value is decremented to zero after the action was executed, the object where the action is in is deleted.

Internally the action details are processed as four sint32 values. This documentation dissects them further where appropriate.

Action Type 1: Transport hacker

Transport Hacker Action Details (16 byte)

0000  int32      Target X
0004  int32      Target Y
0008  int32      Target Z
000C  int32      Target Level

For all three target axis values, if they are 0x4000 or greater, they are ignored and the respective axis is not changed in the transport. The X and Y axes specify tile numbers, the Z axis is interpreted in level units.

In the main game, this axis-preservation is used only on level 2 for the Z axis on the experimental transporter, which incidentally has both platforms at the same height.

If to be considered, the target values are then used as quest value keys to resolve the actual location for the respective axis.

The main game does not make use of this quest value lookup feature. All encounterd values are direct values.

The target level specifies a cross-level transfer to the identified level if the value is smaller than 0x1000. If it is 0x1000 or greater, transportation is only done within the same level, regardless of the value.

Cross-level transport is used only for a same-level transfer on level 4 (restoration chamber), and twice for two groves, to transport the hacker to the restoration chamber on level 6. Other instances are set to 0x2222, which are ignored.

Action Type 2: Change Health

This action is also called "damage", probably based on the first parameter.

Change Health Action Details (16 byte)

0000  int32      Damage delta
0004  int16      Health delta
0006  byte       Health change flag; 0: remove delta, 1: add delta
0007  byte       Damage type -- used if removing health
0008  int16      Power delta
000A  int16      Power change flag; 0: remove delta, 1: add delta
000C  int16      Fatigue delta
000E  int16      Fatigue change flag; 0: add delta, 1: remove delta

All four delta values are used as quest value keys to resolve the actual delta value.

The damage delta is not used in the main game. Although intended to cause explosion damage, due to mixed up parameters in the code, a fixed amount of damage is done, with the delta value being interpreted as damage type.

Reducing health to/below 0 causes death. Reducing power below 0 causes an underflow and hacker is fully powered again.

Action Type 3: Clone/Move Object

This action is internally called "Create Object". Name not kept to describe actual functionality better.

Clone/Move Action Details (16 byte)

0000  int16      Source object index -- quest value key
0002  int16      Move flag
0004  int32      Target X tile
0008  int32      Target Y tile
000C  int32      Target Z

The move flag has a dual purpose. First, it is used to determine whether the object shall be moved or cloned. If it is zero, then the object is cloned; If it has bit 0x1000 set, then the object is cloned as well; All other values cause the source object to be moved. If the object is cloned, then the move flag parameter will be used as quest value key to store the object index of the newly created object.

The game archive has various values for the move flag.

For all three target axis values, if they are 0x4000 or greater, they are ignored and the respective axis is not changed. The X and Y axes specify tile numbers, the Z axis is interpreted in level units.

In the main game, this axis-preservation is used with various values, including 0x4400.

If to be considered, the target values are then used as quest value keys to resolve the actual location for the respective axis.

The orientation and in-tile position of the source object will be kept.

Action Type 4: Set Game Variable

This action is internally called "Quest Bit". Name not kept to describe actual functionality better.

Set Game Variable Action Details (16 byte)

0000  int32      Quest value key
0004  int16      Value
0006  int16      Operation
0008  int32      Message 1 (within resource 0x0867)
000C  int32      Message 2 (within resource 0x0867)

Depending on the quest value key, different sets of variables are modified. The variables are stored in the Game State Structure. If no bit in the nibble of 0xF000 is set, the quest value key defaults to boolean variables.

For the most part in the main game, the boolean variable selector 0x2000 is not set and thus relies on this default handling. There are a few cases where this boolean variable selector is set.

For the int16 variables, value must be in the range 0..0x0FFF. Operation can be one of the following:

0:  Set value
1:  Add value
2:  Subtract value
3:  Multiply with value
4:  Divide by value (Resulting fractions are cut, divide by 0 is ignored)
5:  Modulo by value

For the boolean variables, operation is ignored and always 0. The values are either 0 or 1 to set that value, or 2 to toggle the current value.

If the resulting value is not zero, the (optional) message 1 is played/shown. If the resulting value is zero, the (optional) message 2 is played/shown. Both message parameters are quest value keys.

Operations other than Set or Add are not used in the game for the int16 values.

Action Type 5: Cutscene

Cutscene Action Details (16 byte)

0000  int32      Cutscene index; 0: Death, 1: Intro, 2: Ending
0004  int32      End game flag
0008  [8]byte    Unused

End game flag must be 1. Setting it to 0 leaves the game in an unplayable state after the cutscene.

What happens after the cutscene is dependent on the cutscene itself: The death and intro cutscenes return to the main menu, the ending cutscene ends the game (showing score and credits).

In the regular game, this action is used only once when defeating SHODAN.

Action Type 6: Trigger other objects

Trigger Objects Action Details (16 byte)

0000  int16      Object 1 index
0002  int16      Object 1 delay
...
000C  int16      Object 4 index
000E  int16      Object 4 delay

The delays are all relative to the execution start of the action. Their unit is 0.1 of a second.

All four object indices are quest value keys. They are resolved when this action is executed, not after the delay.

Action Type 7: Change lighting

Change Lighting Action Details (16 byte)

0000  int16      Light type extent - quest value key
0002  int16      Reference object index - quest value key
0004  int16      Transition type. 0x0000: immediate, 0x0001: fade, 0x0100: flicker
0006  int16      Transition state
0008  byte       Light type
0009  byte       Unused
000A  int16      Light surface. 0x0000: floor, 0x0001: ceiling, 0x0002: floor and ceiling
000C  [4]byte    Light type parameter

These actions modify the light deltas of the affected tiles. Such actions can not change the base darkness values of a tile. If a tile is fully bright by default, nothing can change that. The configured light parameters are absolute values.

The transition state is a bitmask storing the state for a change.

Transition state (2 bytes)

0x0FFF  Step counter
0x1000  0: light on, 1: light off

Light type (1 byte)

0x00  Rectangular
0x01  Linear gradient (East-West smooth)
0x02  Linear gradient (North-South smooth)
0x03  Radial gradient

Gradient light type parameter (4 bytes)

0000  byte       Off light begin intensity
0001  byte       Off light end intensity
0002  byte       On light begin intensity
0003  byte       On light end intensity

Rectangular light (type 0x00)

For this light type, the light type extent specifies a second object index. All tiles within this rectangle are affected.

Light type parameter (4 bytes)

0000  byte       Off light value 0x00..0x0F
0001  byte       On light value 0x00..0x0F
0002  [2]byte    Unused

Linear gradient light (types 0x01, 0x02)

For this light type, the light type extent specifies a second object index to define the affected area.

For these types, the gradient light type parameter intensity values have a range of 0x00..0x0F.

These light types are not used in the regular game.

Radial gradient light (type 0x03)

For this light type, the light type extent specifies a radius, in tiles, of affected tiles. The begin of the gradient is always the tile of the triggering object (reference object index is ignored).

The intensity values of the gradient light type parameter have a range of 0x00..0x7F. A value of around 0x14 lights a tile as if it were fully lit. Values above will spill over to the surrounding tiles.

Action Type 8: Effect

Effect Action Details (16 byte)

0000  int16      Sound index, based on 0x00C9; 0: Play nothing
0002  int16      Sound play count; 0: endless
0004  int16      Visual effect
0006  [2]byte    Unused
0008  int16      Additional visual effect
000A  [2]byte    Unused
000C  int16      Additional visual effect time; 0: endless
000E  [2]byte    Unused

All parameters are used as quest value keys.

Visual Effects:

0: None
1: Power on: Dim level lights and fade back to normal; Plays generator sound as well
2: Quake: Shake cam and play rumble sound
3: Escape pod: Shows launch sequence, cam shake and abort; Plays SHODAN message afterwards
4: Red static (fullscreen)
5: Red static (interference)

Additional Visual Effects:

0: None
1: White flash
2: Pink flash
3: Gray static (fullscreen)
4: Vertical panning (including HUD)

Action Type 9: Change tile heights

0000  int32      Tile X
0004  int32      Tile Y
0008  int16      Target floor height; 0..31, measured from floor absolute zero
000A  int16      Target ceiling height; 1..31, measured from floor absolute zero
000C  [2]byte    Unused
000E  int16      Silent flag; 0: play sound, 1: no sound

Tile coordinates, as well as the heights, are used as quest value keys.

For the height fields a value equal to, or greater than 0x0100 indicates "don't move".

The ceiling height has also been encountered to be 0x0020, also not moving.

The silent flag only works for floor changes. If the ceiling changes height, it makes sound regardless of this parameter.

Action Type 10: Change Terrain

0000  int32      Tile X
0004  int32      Tile Y
0008  int32      Tile type
000C  int32      Terrain parameter (slope height)

All four parameters are used as quest value keys.

If tile type or terrain parameter has the bit 0x4000 set, the respective property will not be changed.

This action is not used in the main game.

Action Type 11: Scheduled Trap

Scheduled Trap Action Details (16 byte)

0000  int32      Object index
0004  int32      Time interval
0008  int32      Activation value
000C  int16      Variance
000E  [2]byte    Unused

Parameters object index, time interval, and variance (if set != 0) are used as quest value keys.

The time interval specifies in 0.1 seconds units within which time span the identified object shall be triggered regularly. The variance adds some randomness to the interval. Usually low numbers are encountered in the main game.

The unit of the variance is that of the engine-internal ticks.

The activation value has three different uses:

  • greater than or equal to 0xFFFF: endless scheduling.
  • bit 0x1000 set AND boolean game variable identified by this value key is true: schedule trigger
  • value between 0x0000 (exclusive) and 0x1000 (exclusive): remaining schedule amount, down to zero

The game has the Activation value typically set to 0xFFFF, 0x10000 or 0x11111 in the main game.

Action Type 12: Cycle Objects

Internally, this action is called "Alternating splitter"

Cycle Objects Action Details (16 byte)

0000  [3]int32   Object indices
000C  int32      Next object

All three object indices are interpreted as quest value keys.

This action triggers objects from the list of object indices. The next object field indicates which entry to trigger next. Afterwards, the next object field is incremented. It is reset to 0 if it is either greater than 2, or it is 2 and the third object index is 0.

Action Type 13: Destroy Object

Destroy Object Action Details (16 byte)

0000  int16      Object 1 index
0002  int16      Unused
0004  int16      Object 2 index
0006  int16      Unused
0008  int16      Object 3 index
000A  int16      Unused
000C  int32      Message index (within resource 0x0867); 0: no message 

All three object indices are interpreted as quest value keys.

Action Type 14: Unused

This action is not used and does nothing.

Action Type 15: Receive EMail

Receive EMail Action Details (16 byte)

0000  int16      EMail index, based on 0x0989
0002  [2]byte    Unused
0004  int16      Delay
0008  [10]byte   Unused

The Delay is roughly counted in seconds. Tests showed their actual unit seems to be somewhere at 0.9 seconds.

Action Type 16: Expose

Change Effect Action Details (16 byte)

0000  int16      Delta value
0002  int16      Effect change flag; 0: add delta, 1: remove delta
0004  int32      Effect type
0008  [8]byte    Unused

This action exposes the hacker to some typed hazard or treatment.

Effect types are:

4: Radiation poisoning
8: Bio contamination

The main game uses this only once to remove the radiation in level R - treatment area.

Action Type 17: Set Object Parameter

Set Object Parameter Action Details (16 byte)

0000  int16      Object index 0
0002  int16      Object index 2
0004  int32      Value 1
0008  int32      Value 2
000C  int32      Value 3

Both object indices are treated as quest value keys.

This action sets parameters of target objects. Which value is applied to which parameter is dependent on the target.

The following table lists the mappings.

Target Class Value 1 Value 2 Value 3
Big Stuff Cosmetic value Data1 Data2
Door Locked 0xFF00: Message index, 0x00FF: Cosmetic value 0xFF00: Access level, 0x00FF: Auto-close time
Fixture, Trap Parameter Number (1..4) Parameter Value Unused

For big stuff and door classes, if a value is -1 it doesn't modify the respective target parameter.

Which parameters are specifially affected for fixtures and traps depends on their respective interpretation of the 16 bytes.

Action Type 18: Set Screen Picture

Internally, this action is called "animate".

Set Screen Picture Action Details (16 byte)

0000  int16      Screen 1 object index
0002  int16      Screen 2 object index
0004  int32      Single sequence source
0008  int32      Loop sequence source
000C  int32      Unused

This action sets the picture source for the given screen object(s).

If provided, the Single sequence source is played first. If provided, the Loop sequence is played next and looped. If no loop is provided, the last frame of the single sequence will be kept.

Action Type 19: Hack

This action is a more generic one with several different interpretations, depending on the first field.

Hack Action Details (16 byte)

0000  int32      Hack type
0004  [12]byte   Hack parameter

Hack Action Type 1: Toggle repulsor

Toggle Repulsor Details (12 byte)

0000  int32      Repulsor object index
0004  byte       "Off" texture index (into level texture list)
0005  byte       "On" texture index (into level texture list)
0006  [2]byte    Unused
0008  byte       Toggle type
0009  [3]byte    Unused

Toggle type (1 byte)

0x00  Toggle On/Off
0x01  Toggle On, stay on
0x02  Toggle Off, stay off

Hack Action Type 2: Show Game Code Digit

Show Game Code Digit Details (12 byte)

0000  int32      Screen object index
0004  int32      Digit number 1..6 (= level number)
0008  [4]byte    Unused

Hack Action Type 3: Set Fixture Parameter from Variable

Set Fixture Parameter From Variable Details (12 byte)

0000  int32      Fixture object index
0004  int32      Parameter number (1..4)
0008  int32      Game integer variable index

This hack is used only twice, exclusively to set the codes for the reactor in the base game. Similar to the "Set Object Parameter" action, the interpretation of the modified parameter is depending on the action in the target fixture.

Hack Action Type 4: Set Frame State

Although this hack is called "fixture frame", it doesn't check for the type of the target object and allows to modify any object's frame state.

Set Frame State Details (12 byte)

0000  int32      Button object index
0004  int32      New frame state; 0: off, 1: on
0008  int32      MFD update flag; 0: ignored, != 0: update MFD

Hack Action Type 5: Door Control

Door Control State Details (12 byte)

0000  int32      Door object index
0004  int32      Control value
0008  int32      Unused

Control values:

1: open door
2: close door
3: toggle door
4: disable auto-close

Hack Action Type 6: Return to main menu

This hack has no parameters (all 12 bytes 0x00) and directly returns to the main menu.

Hack Action Type 7: Rotate Object

Rotate Object State Details (12 byte)

0000  int32      Object index
0004  byte       Amount
0005  byte       Type -- 0x00: endless, != 0x00: back/forth
0006  byte       Direction -- 0x00: forward, 0x01 when running backwards
0007  byte       Axis -- 0x00: Z (yaw), 0x01: X (pitch), 0x02: Y (roll)
0008  byte       Forward limit
0009  byte       Backward limit
000A  [2]byte    Unused

This hack rotates an object along one axis. This rotation can be endless in one direction, or a back and forth rotation, depending on the Type field.

If the rotation type is back and forth, then the object is rotated between the two limits. Should the object start outside of these limits, then rotation continues normally until it is within the limits.

If the rotation type is endless, whenever one limit is reached, the object immediately jumps to an orientation as per the other limit.

Hack Action Type 8: Remove Critters

This hack is called "armageddon" internally, most likely in a reference to a similar action in the game Lemmings.

Remove Critters State Details (12 byte)

0000  int32      Object type - 0x00CCSSTT
0004  int32      Radius
0008  int32      Unused

This hack removes critters of the specified object type from the level. The radius specifies how many shall be removed around the tile of the action's object, in tiles.

Avoid using high amounts. The engine can remove only a certain amount of objects in one tick (100) and has no guard if more are removed. A memory overrun occurs in this case.

Hack Action Type 9: SHODAN pixelation

This hack has no parameters (all 12 bytes 0x00) and fills the screen with an image. The used image is hardcoded. The game returns to the main menu after the screen is filled. It should be used only in cyberspace; Using it in real world messes up tile textures.

Hack Action Type 10: Set Condition

Set Condition Details (12 byte)

0000  int32      Object index
0004  [4]byte    Condition
0008  [4]byte    Unused

Sets the condition values of specified object (fixture or trap).

Hack Action Type 11: Show System Analyzer

0000  int32      Page index (0..2)
0004  [8]byte    Unused

Hack Action Type 12: Make Area Radioactive

Internally this hack is called "spew". Yet it only supports spillage of radiation.

Make Area Radioactive Details (12 byte)

0000  int32      Reference object index
0004  int16      Watched object index
0006  int16      Watched object trigger state
0008  int32      Spew type. Only value of 0 supported (= radiation).

The rectangular area defined by reference object and the object of the action emits radiation while watched object is in given state (1 = active/open).

This is used only once, on level 2 for the small room in Beta quadrant. The door is both the reference as well as the watched object.

Hack Action Type 13: Oriented Trigger Object

This hack is exclusively used on level 8 to trigger three different taunts from Diego. Hence it is also called "Diego Taunt" in the source.

Oriented Trigger Object Details (12 byte)

0000  uint16     Horizontal direction
0002  [2]byte    Unused
0004  int32      Object index
0008  [4]byte    Unused

This hack triggers the given object only if the player looks to the given Horizontal direction (+/- 45°). Value 0x0000 specifies north, going clockwise with increasing numbers, meaning:

0x0000  North (matches between NW and NE)
0x4000  East (matches between NE and SE)
0x8000  South (matches between SE and SW)
0xC000  West (matches between SW and NW)

Hack Action Type 14: Close Data MFD

Close Data MFD Details (12 byte)

0000  int32      Displayed object index
0004  [8]byte    Unused

If the specified object is currently displayed in the "Data" MFD, close it and return to previous display.

This hack is used only once to close the keypad panel from the reactor if an invalid combination is entered.

Hack Action Type 15: Earth destruction by laser

This hack has no parameters (all 12 bytes 0x00) and lets the player receive the message about the fired laser. The game continues after the message has played. Images and text are hardcoded.

Hack Action Type 16: Change Critter Type Global

Change Critter Type Global Action Details (16 byte)

0000  int32      Critter type - 0x00CCSSTT
0004  byte       New type
0005  [7]byte    Unused

This hack morphs all critters of given object type in the level and changes their type to the given one. Class and subclass stay the same. Stats, such as healthpoints, are maintained as well.

If new type specifies a value greater than 0x0F, the object will be destroyed.

Action Type 20: Set Tile Textures

This action is not used in the main game.

Set Tile Textures Action Details (16 byte)

0000   int32     Area
0004   int32     Floor Operation
0008   int32     Wall Operation
000C   int32     Ceiling Operation

The area defines a rectangular area of affected tiles. If area is less than 0x10000, then only one tile is affected, identified by 0xXXYY. Otherwise, area is interpreted as two object indices (interpreted as quest value keys), that define the area by their respective location.

The three operation fields identify, per texture, what to do.

Texture Operation (4 byte)

0000   int16     Source filter
0002   int16     Destination texture

If source filter is either equal to or greater than 0x1000, or the tile uses the texture identified by this filter, then set the texture according to destination texture if this value is less than 0x1000.

Said differently, try to set destination texture only if the value is less than 0x1000, and consider only tiles if set as a flood-fill, or if the source matches.

Action Type 21: Set Critter State

Set Critter State Action Details (16 byte)

0000  int16      Filter parameter
0002  int16      Filter type
0004  int32      Area
0008  int32      New critter mood -- ignored if value >= 0x1000
000C  int32      New critter orders -- ignored if value >= 0x1000

Sets the state of critters. See Critters for the enumeration values of critter states.

The filter type parameter defines via bits which critters should be considered and how the filter parameter is interpreted.

Filter Type Bitfield (2 byte)

0x0001  Consider loner critters only. If not set, only consider pack critters.
0x0002  Ignore loner/pack property of critter.
0x0004  If set, ```filter parameter``` identifies one specific critter to affect (regardless of remaining bits). Use area otherwise.
0x0008  Affect every critter in the area, regardless of subtype/type. (Note: only works for small areas)

If neither bits 0x0004, nor 0x0008 are set, then filter parameter specifies the subclass and type of affected critters (0xSSTT).

The area parameter defines the affected tiles in the following ways:

  • All zero: affect entire level
  • Lower 16 bits zero: upper 16 bits define half of the side-length of a square, with the tile of the action object at its center.
  • Two 16 bit values identifying reference objects that define a rectangular area.

Unless the new critter mood is friendly, mood is ignored on combat level 0.

Action Type 22: Trap Message

Internally, such messages are called "barks".

Trap Message Action Details (16 byte)

0000  sint32     Background image
0004  int32      Message index (within resource 0x0867)
0008  int32      Text colour
000C  int32      MFD suppression flag; 0: Show in MFD, 1: Show only in HUD

The Background image and Text colour are only considered for display in MFD. The user needs to have messages set to "text" or "both" to see them.

For the Background image, the following values are possible:

-1  SHODAN (black and white)
-2  Diego

The game uses other image references as well, yet they don't work. This is due to the code being modified to ignore positive background image values.

Action Type 23: Spawn Objects

Spawn Objects Action Details (16 byte)

0000  int32      Object type; Format 0x00CCSSTT
0004  int32      Area
0008  int32      Quantity - quest value key
000C  int32      Flags

This action spawns a random number of objects, randomly distributed within an area. The spawned objects are placed at the floor in the center of the tile.

The area field specifies a rectangular area, either based on two objects, or a square. If area is less than 0x10000, then it specifies half of the final side-length of the resulting square, and the trap object's location is at the lower-right corner of this square. Otherwise, area specifies two object indices that define the rectangle with their locations.

Objects are only spawned if the Combat value is 1 or higher. If it is 3, then one more object than requested is spawned. Not all classes can be spawned.

Although the game uses enemies exclusively, ammo, explosives, and patches can be spawned as well.

Spawn Objects Flags (4 byte)

0x00000001       Avoid spawn if tile is within a distance of 7 based on the sum of X and Y deltas.
0x00000002       Avoid spawn if hacker looks at the tile within a distance of 14 based on the sum of X and Y deltas.
0x00000004       Allow spawn if tile is an elevator tile (identified by elevator music).
0x00000008       Force spawn, even if the ceiling is too low, or the tile contains already a critter.

Action Type 24: Change Object Type

Internally, this action is called "transmogrify".

Change Object Type Action Details (16 byte)

0000  int32      Object index
0004  int16      New type
0006  int16      Reset mask
0008  [8]byte    Unused

This action sets, or toggles, the type of an object. It is primarily used to extend and retract force bridges.

For bridges in their retracted state, the game uses "Elephant, Jorp" (7/7/8), an invisible placeholder type.

The Reset mask is used when the specified object is already at given type. If the specified object is already at given type, then the new type is calculated as New type XOR Reset mask.

So, to toggle between 0x08 and 0x09, New type should be 0x08 and Reset mask must be set to 0x01. To toggle between 0x08 and 0x07, New type should be 0x07 and Reset mask must be set to 0x0F.

The first byte of unused field at 0008 is set to 1 for only one force bridge in the game (on level 2) and is ignored. It appears that an earlier version of the code supported suppressing of animations.