Adding modding folder with a hacked build.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
## Contributing Guidelines
|
||||
|
||||
Thank you for considering to contribute to this documentation!
|
||||
Such a contribution can be useful for modders, tool-, and engine developers.
|
||||
|
||||
The following text lists guidelines for contributing to this documentation.
|
||||
These guidelines don't have legal status, so use them as a reference and common sense - and feel free to update them as well!
|
||||
|
||||
|
||||
### "I just want to know..."
|
||||
|
||||
For questions, or general meta-information about the engine or the data files, please refer to the [systemshock.org](https://www.systemshock.org) forums.
|
||||
The following sub-sections will most likely be applicable for your question:
|
||||
|
||||
* [Engineering](https://www.systemshock.org/index.php?board=36.0) - for modding the game or creating fan-missions in general
|
||||
* [Deck 13](https://www.systemshock.org/index.php?board=13.0) - for engine source-code, ports, and tool-development related topics
|
||||
* [System Shock source code](https://github.com/nothings/shockmac) - source code of System Shock for Mac OS with notes from Sean Barrett
|
||||
|
||||
### Scope
|
||||
|
||||
This documentation is meant to describe the "meaningful" resource files of the original System Shock (1994) and related engine behaviour.
|
||||
It is meant to give modders and tool-developers (possibly engine developers) a reference on what data to expect.
|
||||
|
||||
What does "meaningful" mean? Data that has effect on the players experience. As a rule of thumb, there are several fields in various structures that are unused. Even with the source code of the engine available, it may be academic to try to document fields and their fictionial behaviour just by their name alone. If a field is never used, it may simply be stated as such and nothing more.
|
||||
Exceptions are listed on the main readme - for instance, not covering music or Mac-specific files.
|
||||
|
||||
What does "original" mean? The game System Shock from 1994 and its direct derivatives, such as the "Enhanced Edition" or possible (future) source ports that claim to be compatible with the data files. It may be that future source ports extend the behaviour of the original engine. If this is the case, this documentation could be extended alongside, stating the compatibilities.
|
||||
|
||||
This documentation is NOT a documentation on the engine itself. There may be some gray areas if related to behaviour, yet you won't find a documentation on how the renderer is working for instance.
|
||||
|
||||
|
||||
### Conventions
|
||||
|
||||
This documentation is meant to be read by a Markdown-compatible viewer, though for the most part, this will remain GitHub itself.
|
||||
Refer to the [conventions](conventions.md) document for formatting and content.
|
||||
|
||||
To reiterate from this document: Please avoid adding information "on a hunch" to the documentation. Meanwhile the source code has already been released, so if there isn't a test, or a successful tool showcasing information, the documentation should at least hold up to the original source code.
|
||||
|
||||
It is acceptable to change field/type names if they are "near" synonyms (or simply words written in full). The documentation should aim to stay close to the original source, not a particular fan-project (not even tools from InkyBlackness - their code should follow as well.)
|
||||
|
||||
|
||||
### Information
|
||||
|
||||
As a rule of thumb, this documentation describes types (data structures) with their fields, names, and related behaviour of the engine.
|
||||
This is typically a combination of a dry listing of a data structure, as described in the conventions, and then some paragraphs of prose text.
|
||||
|
||||
It should not contain any source code - especially copied from the original source, which uses a different license. The only algorithms explained in this documentation are that of compression, and even these could be covered in prose.
|
||||
|
||||
|
||||
### Adding/Changing the documentation
|
||||
|
||||
If you find typos, new information, better (more expressive) descriptions that you would like to see handled, feel free to create an issue, or possibly even a pull-request about this.
|
||||
@@ -0,0 +1 @@
|
||||
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
|
||||
@@ -0,0 +1,32 @@
|
||||
# THE UNOFFICIAL SYSTEM SHOCK 1 SPECIFICATIONS
|
||||
|
||||
This is a sub-project as part of the [InkyBlackness](https://inkyblackness.github.io) project. It aims to document the data (resource) files of the video game [System Shock](http://en.wikipedia.org/wiki/System_Shock). It is the continuation of the previous work performed as part of "The System Shock Hack Project" ([TSSHP](http://tsshp.sourceforge.net/)).
|
||||
|
||||
The goal is to document all meaningful bits and bytes of the original data files.
|
||||
|
||||
Start reading with the [main page](index.md) (the index).
|
||||
|
||||
If you would like to contribute to the documentation, please consider [the guidelines](CONTRIBUTING.md).
|
||||
|
||||
## Status
|
||||
The content of this documentation supersedes the information available from TSSHP (the [ss-specs.txt](http://tsshp.cvs.sourceforge.net/viewvc/tsshp/tsshp/doc/ss-specs.txt?view=markup) file). In some instances, this documentation even provides more accurate descriptions.
|
||||
|
||||
The format of all raw media content is described, with the exception of a few unknown fields. The same counts for the game objects.
|
||||
See the [issue list](https://github.com/inkyblackness/ss-specs/issues) for an overview about what is still actively analyzed.
|
||||
With the release of the original source (see credits below), many so far unknown things can be clarified.
|
||||
|
||||
Currently not in scope of this documentation project are music files (See [here for details](other/Music.md)) and the Macintosh release.
|
||||
|
||||
|
||||
## Credits
|
||||
* This project, as well as InkyBlackness itself, wouldn't be possible without the work of TSSHP and the effort of the people before that.
|
||||
* [Source release](https://github.com/NightDiveStudios/shockmac) of the Mac version, which finally allowed to figure out unknown details, and set some guesswork naming right.
|
||||
|
||||
## License
|
||||
|
||||
[![License][license-image]][license-url]
|
||||
|
||||
This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-nc-sa/4.0/).
|
||||
|
||||
[license-url]: http://creativecommons.org/licenses/by-nc-sa/4.0/
|
||||
[license-image]: https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png
|
||||
@@ -0,0 +1,336 @@
|
||||
## Game state and hacker information, resource 0x0FA1 (`Player` struct)
|
||||
|
||||
This resource contains everything about the hacker, together with general game-state information.
|
||||
|
||||
|
||||
0000 20xbyte Hacker name (incl. 0x00 termination char). Game only allows 12 characters for input at start.
|
||||
0014 byte Realspace Level; The level to return to after exiting cyberspace.
|
||||
|
||||
0015 4xbyte Difficulties (Game rating): combat, mission, puzzle, cyber. All 0..3
|
||||
0019 3xbyte Unused.
|
||||
|
||||
001C uint32 Game time
|
||||
0020 uint32 Last second update
|
||||
0024 uint32 Last drug update
|
||||
0028 uint32 Last ware update
|
||||
002C uint32 Last animation check
|
||||
0030 int32 Queue Time
|
||||
0034 int32 Delta Time
|
||||
0038 byte Detail Level
|
||||
|
||||
0039 byte Current level identifier
|
||||
003A 22xint16 Initial SHODAN levels
|
||||
0066 6xbyte Controls
|
||||
006C int16 Player Object ID
|
||||
006E [8]byte Realspace location; The point to return to after exiting cyberspace.
|
||||
0076 int32 Version number of the data structure; Value: 6
|
||||
007A [14]int16 General inventory references, Object IDs
|
||||
|
||||
0096 byte Posture
|
||||
0097 byte Foot planted; 1: on the floor
|
||||
0098 byte Lean X
|
||||
0099 byte Lean Y
|
||||
009A int16 Unused
|
||||
|
||||
009C byte Health; 0x00..0xFF
|
||||
009D byte Cyberspace Integrity
|
||||
009E uint16 Hitpoint regeneration per minute
|
||||
00A0 8xbyte Damage rate per minute [explosion, energy, magnetic, radiation, gas, tranq, needle, bio]
|
||||
00A8 uint16 Bio post expose
|
||||
00AA uint16 Rad post expose
|
||||
00AC byte Power 0x00..0xFF
|
||||
00AD byte Power usage in JPM
|
||||
00AE byte Power regeneration
|
||||
00AF byte Energy out; 1: is out of energy
|
||||
00B0 int16 Cyberspace trips
|
||||
00B2 int32 Cyberspace time base
|
||||
|
||||
00B6 [64]uint8 512 Boolean game variables; Bytes are counted up, bits within byte counted from LSB; Example: bit[10] = 0x00 0x04 0x..
|
||||
00F6 [64]int16 64 Integer game variables
|
||||
|
||||
0176 uint32 HUD modes; Bitfield as per hud.h
|
||||
017A byte Unused
|
||||
017B sint32 Fatigue
|
||||
017F uint16 Fatigue spending; Current rate of fatigue expenditure in pts/sec
|
||||
0181 uint16 Fatigue regeneration
|
||||
0183 uint16 Fatigue regeneration base
|
||||
0185 uint16 Fatigue regeneration maximum
|
||||
0187 sint8 Accuracy
|
||||
0188 byte Shield absorb rate, in percent
|
||||
0189 byte Shield threshold
|
||||
018A byte Light value; setting of lamp
|
||||
|
||||
Multi-Function-Display (MFD) state
|
||||
018B [10]byte 2x5 MFD slot indices
|
||||
0195 [7]byte MFD status
|
||||
019C [7]byte MFD function IDs
|
||||
01A3 [32]byte MFD function flags
|
||||
01C3 [256]byte MFD function data
|
||||
02C3 [2]byte current MFDs
|
||||
02C5 [2]byte MFD empty functions
|
||||
02C7 [64]byte MFD access puzzles
|
||||
0307 [2]byte MFD save slots
|
||||
|
||||
|
||||
Installed Hardware (0: not installed):
|
||||
0309 byte version for infrared night vision
|
||||
030A byte version for target info
|
||||
030B byte version for Sensaround
|
||||
030C byte version for "Aim Enhancement Hardware"
|
||||
030D byte version for HUD (unknown function)
|
||||
030E byte version for bioscan
|
||||
030F byte version for navigation unit
|
||||
0310 byte version for shield
|
||||
0311 byte version for data reader
|
||||
0312 byte version for lantern
|
||||
0313 byte version for view control
|
||||
0314 byte version for enviro suit
|
||||
0315 byte version for booster
|
||||
0316 byte version for jump jet
|
||||
0317 byte version for system status
|
||||
|
||||
Installed Software(0: not installed):
|
||||
0318 [7]byte offensive software
|
||||
031F [3]byte defensive software
|
||||
0322 [9]byte misc software
|
||||
|
||||
Full clips of ammunition
|
||||
032B byte ML STANDARD ROUNDS
|
||||
032C byte ML TEFLON COATED ROUNDS
|
||||
032D byte SV NEEDLE DARTS
|
||||
032E byte SV TRANQ DARTS
|
||||
032F byte HOLLOW-TIP 2100 CLIP
|
||||
0330 byte HEAVY SLUG 2100 CLIP
|
||||
0331 byte DC RUBBER SLUGS
|
||||
0332 byte MARK3 MAGNESIUM-TIP SHELLS
|
||||
0333 byte MARK3 PENETRATOR SHELLS
|
||||
0334 byte AM HORNET CLIP
|
||||
0335 byte AM SPLINTER CLIP
|
||||
0336 byte RF SLAG CLIP
|
||||
0337 byte RF LARGE SLAG CLIP
|
||||
0338 byte SG MAG PULSE CART
|
||||
0339 byte MM RAIL CLIP
|
||||
|
||||
Ammunition not in full clips
|
||||
033A byte ML STANDARD ROUNDS
|
||||
033B byte ML TEFLON COATED ROUNDS
|
||||
033C byte SV NEEDLE DARTS
|
||||
033D byte SV TRANQ DARTS
|
||||
033E byte HOLLOW-TIP 2100 CLIP
|
||||
033F byte HEAVY SLUG 2100 CLIP
|
||||
0340 byte DC RUBBER SLUGS
|
||||
0341 byte MARK3 MAGNESIUM-TIP SHELLS
|
||||
0342 byte MARK3 PENETRATOR SHELLS
|
||||
0343 byte AM HORNET CLIP
|
||||
0344 byte AM SPLINTER CLIP
|
||||
0345 byte RF SLAG CLIP
|
||||
0346 byte RF LARGE SLAG CLIP
|
||||
0347 byte SG MAG PULSE CART
|
||||
0348 byte MM RAIL CLIP
|
||||
|
||||
Patches
|
||||
0349 byte STAMINUP STIMULANT
|
||||
034A byte SIGHT VISION ENCHANCEMENT
|
||||
034B byte BERSERK COMBAT BOOSTER
|
||||
034C byte MEDIPATCH HEALING AGENT
|
||||
034D byte REFLEX REACTION AID
|
||||
034E byte GENIUS MIND-ENCHANCER
|
||||
034F byte DETOX UNIVERSAL ANTIDOTE
|
||||
|
||||
Explosives
|
||||
0350 byte FRAGMENTATION GRENADE
|
||||
0351 byte EMP GRENADE
|
||||
0352 byte GAS GRENADE
|
||||
0353 byte CONCUSSION BOMB
|
||||
0354 byte LAND MINE
|
||||
0355 byte NITROPACK
|
||||
0356 byte EARTH SHAKER EXPLOSIVE
|
||||
|
||||
0357 [294]byte Message status bitfield; 47 emails + 23 data fragments + (16 logs * 14 levels)
|
||||
047D [14]byte Level log marker; On which level logs are in inventory
|
||||
|
||||
048B [5]byte First weapon
|
||||
+0 byte Subclass (0xFF means no weapon)
|
||||
+1 byte Type
|
||||
+2 byte Rounds / Heat
|
||||
+3 byte Ammunition type / Energy setting (0x80 bit is overload)
|
||||
+4 byte Unused
|
||||
|
||||
0490 [5]byte Second weapon
|
||||
0495 [5]byte Third weapon
|
||||
049A [5]byte Fourth weapon
|
||||
049F [5]byte Fifth weapon
|
||||
04A4 [5]byte Sixth weapon
|
||||
04A9 [5]byte Seventh weapon
|
||||
|
||||
04AE [15]byte Hardware on/off
|
||||
04BD [19]byte Software status on/off
|
||||
|
||||
04D0 byte Jumpjet energy fraction
|
||||
04D1 [32]byte email sender count
|
||||
04F1 [7]byte Patches time remainder
|
||||
04F8 [7]byte Patches intensity
|
||||
|
||||
04FF [7]uint16 Timer settings of explosives, in 0.1 seconds; Default: 0x46 = 7 seconds
|
||||
|
||||
050D uint16 Unused
|
||||
050F uint16 Time to completion of current program (seconds). Essentially unused, although used to print some strings
|
||||
|
||||
0511 uint16 ObjectID of current target
|
||||
0513 uint32 Last weapon fire time
|
||||
0517 uint16 Weapon fire rate; Time needed before next fire.
|
||||
|
||||
0519 [10]byte HUD actives: weapon, grenade, drug, cart, hardware, combat soft, defense soft, misc soft, general, email
|
||||
|
||||
0523 uint16 Object under cursor before cyberspace
|
||||
0525 uint16 Last panel reference
|
||||
|
||||
0527 sint32 Kill count
|
||||
052B sint32 Time in cyberspace
|
||||
052F sint32 Number of shots fired
|
||||
0533 sint32 Number of hits
|
||||
|
||||
0537 sint32 Death count; How often hacker was resurrected.
|
||||
053B int32 Tilt (eye position)
|
||||
|
||||
053F [12]fix Physics state (EDMS) - see below
|
||||
|
||||
056F byte Currently active inventory category
|
||||
0570 byte Active bio tracks
|
||||
|
||||
0571 int16 current email
|
||||
|
||||
0573 [6]byte version
|
||||
0579 byte dead flag
|
||||
057A uint16 lean filter state
|
||||
057C [2]byte unused
|
||||
057E byte MFD save field
|
||||
|
||||
057F uint32 Auto fire click
|
||||
0583 uint32 Posture state
|
||||
0587 byte Option: Text Length (0: normal, 1: terse)
|
||||
0588 uint32 Last head bob
|
||||
058C [9]byte Padding
|
||||
|
||||
|
||||
> In archive.dat, this table is (nearly) all 0x00, and also slightly smaller than necessary.
|
||||
|
||||
|
||||
### Physics state (EDMS `State` structure, 48 bytes)
|
||||
|
||||
0000 fix X Coordinate (East -> West)
|
||||
0004 fix Y Coordinate (North -> South)
|
||||
0008 fix Z Coordinate (above ground)
|
||||
000C fix Yaw; 0 is facing East, going counter-clockwise
|
||||
0010 fix Upper body back force (?)
|
||||
0014 fix Upper body left force (?)
|
||||
0018 fix Forward force (?) -- X dot product
|
||||
001C fix Left force (?) -- Y dot product
|
||||
0020 fix Unknown -- Z dot product
|
||||
0024 fix Unknown
|
||||
0028 fix Unknown
|
||||
002C fix Unknown
|
||||
|
||||
Rotation values are in range 0..2PI.
|
||||
|
||||
### Message status enumeration (1 byte)
|
||||
|
||||
0x80 Message received
|
||||
0x40 Message read
|
||||
0x3F Unused
|
||||
|
||||
|
||||
### Game variables
|
||||
|
||||
Game variables are described on a [separate page](gameVariables.md)
|
||||
|
||||
### Initial game state
|
||||
|
||||
The original engine does not allow for having `archive.dat` specify the initial state for both the game and hacker.
|
||||
|
||||
The `System Shock Enhanced Edition Source Port` introduced a modified start behaviour,
|
||||
which allows for (almost) full control on how and where the protagonist starts:
|
||||
When the first field of the `physics state` (the `X` coordinate of EDMS state) is not zero,
|
||||
then most default settings are skipped, and data is taken from `archive.dat`.
|
||||
Still, some minimal setup is performed either way, in order to have a stable game.
|
||||
|
||||
> This behaviour exists already in the original engine, but it only considers the physics structure itself,
|
||||
> and no further information, such as the current level or any game variable.
|
||||
|
||||
#### Mission-independent hardcoded defaults
|
||||
|
||||
The following defaults are being applied regardless of existing data in `archive.dat`.
|
||||
|
||||
##### Game state fields
|
||||
|
||||
| Offset | Name | Initial value |
|
||||
|--------|----------------------------|-----------------------------------------------------|
|
||||
| 0000 | Hacker name | as per start menu |
|
||||
| 0015 | Difficulties | as per start menu |
|
||||
| 0038 | Detail Level | as per configuration |
|
||||
| 003A | Initial SHODAN levels | all to `-1` |
|
||||
| 006C | Player Object ID | `0` |
|
||||
| 00A0 | Damage rate per minute | all to `0` |
|
||||
| 0511 | ObjectID of current target | `0` |
|
||||
| 0513 | Last weapon fire time | `0` |
|
||||
| ** | Various MFD fields | To a consistent (empty) MFD display |
|
||||
| 0309 | Installed Hardware[10] | `1` to hardcode "fullscreen hardware" |
|
||||
| 0570 | Active bio tracks | `0xFF` |
|
||||
| 00F6 | Integer game variables[48] | Language, as per configuration |
|
||||
|
||||
The two "random" game variables (index 31 and 32) are randomized only if they are equal.
|
||||
|
||||
|
||||
#### Mission-dependent defaults
|
||||
|
||||
The following defaults are being applied *only* if `physics state` field `X` is zero.
|
||||
|
||||
##### Game state fields
|
||||
|
||||
| Offset | Name | Initial value |
|
||||
|--------|----------------------------|-----------------------------------------------------|
|
||||
| 0039 | Current level identifier | `1` |
|
||||
| 007A | General Inventory | all to `0` |
|
||||
| 009C | Health | `212` |
|
||||
| 009D | Cyberspace Integrity | `255` |
|
||||
| 009E | Hitpoint regeneration | `0` |
|
||||
| 00AC | Power | `255` |
|
||||
| 00B2 | Cyberspace time base | `504000` (30 minutes in 280 ticks-per-second) |
|
||||
| 0181 | Fatigue regeneration | `0` |
|
||||
| 0183 | Fatigue regeneration base | `100` |
|
||||
| 0183 | Fatigue regeneration max | `400` |
|
||||
| 0187 | Accuracy | `100` |
|
||||
| 0188 | Shield absorb rate | `0` |
|
||||
| 0357 | Message status[26] | `0x80`, to mark email from Rebecca received |
|
||||
| 048B | Weapons[*].type | `0xFF`, to mark no weapon in slot |
|
||||
| 04FF | Explosives timer[*] | `70` (= 7 seconds) |
|
||||
| 0519 | HUD actives[9] | `0xFF`, to mark email being active |
|
||||
| 053F | Physics state (EDMS) | X=30.5, Y=22.5, Z=planted at floor, Alpha=West |
|
||||
|
||||
|
||||
##### Variables
|
||||
|
||||
The following integer variables are set:
|
||||
|
||||
| Integer | Value |
|
||||
|---------|--------|
|
||||
| 3 | 2 |
|
||||
| 12 | 3 |
|
||||
| 51 | 256 |
|
||||
|
||||
And the following boolean variables are set to `true`:
|
||||
|
||||
```
|
||||
0x001, 0x002, 0x003, 0x010, 0x012, 0x015, 0x016, 0x017, 0x018, 0x019, 0x01A,
|
||||
0x020, 0x021, 0x024, 0x025,
|
||||
0x04B, 0x04C, 0x04D, 0x04E, 0x04F,
|
||||
0x050, 0x051, 0x052, 0x053, 0x054, 0x055, 0x056, 0x057, 0x058, 0x059, 0x05A, 0x05B, 0x05C, 0x05D, 0x05E, 0x05F,
|
||||
0x070, 0x071, 0x072, 0x073, 0x074, 0x075, 0x076, 0x077, 0x078, 0x079, 0x07A, 0x07B, 0x07C, 0x07D, 0x07E, 0x07F,
|
||||
0x0A0, 0x0A1, 0x0A2, 0x0A3, 0x0A4, 0x0A5, 0x0A6, 0x0A7, 0x0A8, 0x0A9,
|
||||
0x0C0, 0x0C1, 0x0C2, 0x0C3, 0x0C4, 0x0C5, 0x0C6, 0x0C7, 0x0C8, 0x0C9, 0x0CA, 0x0CB, 0x0CC, 0x0CD, 0x0CE, 0x0CF,
|
||||
0x0E1, 0x0E3, 0x0E5, 0x0E7, 0x0E9, 0x0EB, 0x0ED, 0x0EF,
|
||||
0x0F1, 0x0F3, 0x0F5, 0x0F7, 0x0F9, 0x0FB, 0x0FD, 0x0FF,
|
||||
0x101, 0x103, 0x105, 0x107, 0x109, 0x10B, 0x10D, 0x10F,
|
||||
0x111, 0x113, 0x115, 0x117, 0x119, 0x11B, 0x11D, 0x11F,
|
||||
0x121, 0x123, 0x125, 0x127, 0x129, 0x12B,
|
||||
```
|
||||
@@ -0,0 +1,208 @@
|
||||
## Game variables
|
||||
|
||||
This page lists all game variables with their index, their initital value, and their usage in the original game.
|
||||
|
||||
> At the moment not all variables have been catalogued. Only the initial values have been determined.
|
||||
|
||||
### Boolean variables
|
||||
|
||||
| Index | Initial Value | Usage |
|
||||
|------:|--------------:|----------------------------------------------------------------------------------------------|
|
||||
| 0 | 0 | Must always be 0, otherwise default conditions may break |
|
||||
| 1 | 1 | Must always be 1, otherwise some locks may fail |
|
||||
| 2 | 1 | Unknown |
|
||||
| 3 | 1 | Unknown |
|
||||
| 6 | 0 | Shield status (+ System Analyzer) |
|
||||
| 8 | 0 | Laser status (+ System Analyzer); 0: charging, 1: destroyed |
|
||||
| 10 | 0 | Delta grove launch enable (+ System Analyzer) |
|
||||
| 11 | 0 | Alpha grove launch enable (+ System Analyzer) |
|
||||
| 12 | 0 | Beta grove launch enable (+ System Analyzer) |
|
||||
| 13 | 0 | Relay 428 report status; 0: functioning, 1: faulty; Set by main switch, checked by diag. |
|
||||
| 14 | 0 | Relay 428 repair status; 0: faulty, 1: fixed; Set by panel, checked by main switch. |
|
||||
| 15 | 0 | Beta grove jettisoned (+ System Analyzer) |
|
||||
| 16 | 1 | Unknown |
|
||||
| 18 | 1 | Unknown |
|
||||
| 20 | 0 | Reactor on destruct, pods enabled; Quakes (+ System Analyzer) |
|
||||
| 21 | 1 | Unknown |
|
||||
| 22 | 1 | Unknown |
|
||||
| 23 | 1 | Unknown |
|
||||
| 24 | 1 | Unknown |
|
||||
| 25 | 1 | Unknown |
|
||||
| 26 | 1 | Medical armory lock on doors in level 1 |
|
||||
| 30 | 0 | Switch to open armory doors on level 1 via cyberspace level 14 |
|
||||
| 32 | 1 | Unknown |
|
||||
| 33 | 1 | Unknown |
|
||||
| 36 | 1 | Unknown |
|
||||
| 37 | 1 | Unknown |
|
||||
| 75 | 1 | Unknown |
|
||||
| 76 | 1 | Unknown |
|
||||
| 77 | 1 | Unknown |
|
||||
| 78 | 1 | Unknown |
|
||||
| 79 | 1 | Unknown |
|
||||
| 80 | 1 | Unknown |
|
||||
| 81 | 1 | Unknown |
|
||||
| 82 | 1 | Unknown |
|
||||
| 83 | 1 | Unknown |
|
||||
| 84 | 1 | Unknown |
|
||||
| 85 | 1 | Unknown |
|
||||
| 86 | 1 | Unknown |
|
||||
| 87 | 1 | Unknown |
|
||||
| 88 | 1 | Unknown |
|
||||
| 89 | 1 | Unknown |
|
||||
| 90 | 1 | Unknown |
|
||||
| 91 | 1 | Unknown |
|
||||
| 92 | 1 | Unknown |
|
||||
| 93 | 1 | Unknown |
|
||||
| 94 | 1 | Unknown |
|
||||
| 95 | 1 | Unknown |
|
||||
| 112 | 1 | Unknown |
|
||||
| 113 | 1 | Unknown |
|
||||
| 114 | 1 | Unknown |
|
||||
| 115 | 1 | Unknown |
|
||||
| 116 | 1 | Unknown |
|
||||
| 117 | 1 | Unknown |
|
||||
| 118 | 1 | Unknown |
|
||||
| 119 | 1 | Unknown |
|
||||
| 120 | 1 | Unknown |
|
||||
| 121 | 1 | Unknown |
|
||||
| 122 | 1 | Unknown |
|
||||
| 123 | 1 | Unknown |
|
||||
| 124 | 1 | Unknown |
|
||||
| 125 | 1 | Unknown |
|
||||
| 126 | 1 | Unknown |
|
||||
| 127 | 1 | Unknown |
|
||||
| 145 | 0 | "Online" help (tooltips); 0: show, 1: off |
|
||||
| 160 | 1 | Unknown |
|
||||
| 161 | 1 | Unknown |
|
||||
| 162 | 1 | Unknown |
|
||||
| 163 | 1 | Unknown |
|
||||
| 164 | 1 | Unknown |
|
||||
| 165 | 1 | Unknown |
|
||||
| 166 | 1 | Unknown |
|
||||
| 167 | 1 | Unknown |
|
||||
| 168 | 1 | Unknown |
|
||||
| 169 | 1 | Unknown |
|
||||
| 192 | 1 | Unknown |
|
||||
| 193 | 1 | Unknown |
|
||||
| 194 | 1 | Unknown |
|
||||
| 195 | 1 | Unknown |
|
||||
| 196 | 1 | Unknown |
|
||||
| 197 | 1 | Unknown |
|
||||
| 198 | 1 | Unknown |
|
||||
| 199 | 1 | Unknown |
|
||||
| 200 | 1 | Unknown |
|
||||
| 201 | 1 | Unknown |
|
||||
| 202 | 1 | Unknown |
|
||||
| 203 | 1 | Unknown |
|
||||
| 204 | 1 | Unknown |
|
||||
| 205 | 1 | Unknown |
|
||||
| 206 | 1 | Unknown |
|
||||
| 207 | 1 | Unknown |
|
||||
| 225 | 1 | Unknown |
|
||||
| 227 | 1 | Unknown |
|
||||
| 229 | 1 | Unknown |
|
||||
| 231 | 1 | Unknown |
|
||||
| 233 | 1 | Unknown |
|
||||
| 235 | 1 | Unknown |
|
||||
| 237 | 1 | Unknown |
|
||||
| 239 | 1 | Unknown |
|
||||
| 241 | 1 | Unknown |
|
||||
| 243 | 1 | Unknown |
|
||||
| 245 | 1 | Unknown |
|
||||
| 247 | 1 | Unknown |
|
||||
| 249 | 1 | Unknown |
|
||||
| 251 | 1 | Unknown |
|
||||
| 253 | 1 | Unknown |
|
||||
| 255 | 1 | Unknown |
|
||||
| 257 | 1 | Unknown |
|
||||
| 259 | 1 | Unknown |
|
||||
| 261 | 1 | Unknown |
|
||||
| 263 | 1 | Unknown |
|
||||
| 265 | 1 | Unknown |
|
||||
| 267 | 1 | Unknown |
|
||||
| 269 | 1 | Unknown |
|
||||
| 271 | 1 | Unknown |
|
||||
| 273 | 1 | Unknown |
|
||||
| 275 | 1 | Unknown |
|
||||
| 277 | 1 | Unknown |
|
||||
| 279 | 1 | Unknown |
|
||||
| 281 | 1 | Unknown |
|
||||
| 283 | 1 | Unknown |
|
||||
| 285 | 1 | Unknown |
|
||||
| 287 | 1 | Unknown |
|
||||
| 289 | 1 | Unknown |
|
||||
| 291 | 1 | Unknown |
|
||||
| 293 | 1 | Unknown |
|
||||
| 295 | 1 | Unknown |
|
||||
| 297 | 1 | Unknown |
|
||||
| 299 | 1 | Unknown |
|
||||
| 300 | 0 | Set to 1 while the data reader icon is flashing & beeping |
|
||||
|
||||
|
||||
### Integer variables
|
||||
|
||||
| Index | Initial Value | Usage |
|
||||
|------:|--------------:|---------------------------------------------------------|
|
||||
| 1 | 0 | Incremented for each destroyed computer node lvls 1-7 |
|
||||
| 3 | 2 | Engine state |
|
||||
| 9 | 0 | Incremented by 1 for laser, beta grove, reactor |
|
||||
| 12 | 3 | Number of groves |
|
||||
| 13 | Mission value | Unknown |
|
||||
| 14 | Cyber value | Unknown |
|
||||
| 15 | Combat value | Unknown |
|
||||
| 16 | L00 security | Security value of level |
|
||||
| 17 | L01 security | Security value of level |
|
||||
| 18 | L02 security | Security value of level |
|
||||
| 19 | L03 security | Security value of level |
|
||||
| 20 | L04 security | Security value of level |
|
||||
| 21 | L05 security | Security value of level |
|
||||
| 22 | L06 security | Security value of level |
|
||||
| 23 | L07 security | Security value of level |
|
||||
| 24 | L08 security | Security value of level |
|
||||
| 25 | L09 security | Security value of level |
|
||||
| 26 | L10 security | Security value of level |
|
||||
| 27 | L11 security | Security value of level |
|
||||
| 28 | L12 security | Security value of level |
|
||||
| 29 | L13 security | Security value of level |
|
||||
| 30 | Puzzle value | Unknown |
|
||||
| 31 | random | Reactor code 1 (3-digit BCD) |
|
||||
| 32 | random | Reactor code 2 (3-digit BCD) |
|
||||
| 33 | 0 | Destroyed comp. nodes on lvl1 before showing digit |
|
||||
| 34 | 0 | Destroyed comp. nodes on lvl2 before showing digit |
|
||||
| 35 | 0 | Destroyed comp. nodes on lvl3 before showing digit |
|
||||
| 36 | 0 | Destroyed comp. nodes on lvl4 before showing digit |
|
||||
| 37 | 0 | Destroyed comp. nodes on lvl5 before showing digit |
|
||||
| 38 | 0 | Destroyed comp. nodes on lvl6 before showing digit |
|
||||
| 39 | 0 | Destroyed cyberguards in large cspace / open barrier |
|
||||
| 40 | | Unknown |
|
||||
| 41 | as per config | Audio music volume (0x00 .. 0x64) |
|
||||
| 42 | 0x4A3D | Video gamma |
|
||||
| 43 | as per config | Audio digital FX volume (0x00 .. 0x64) |
|
||||
| 44 | as per config | Mouse handedness (Right: 0, Left: 1) |
|
||||
| 45 | | Unknown |
|
||||
| 46 | | Unknown |
|
||||
| 47 | 0x5555 | Double click time |
|
||||
| 48 | as per config | Selected language (0: ENG, 1: FRA, 2: GER) |
|
||||
| 49 | as per config | Audio message volume (0x00 .. 0x64) |
|
||||
| 50 | as per config | Video resolution |
|
||||
| 51 | 256 | Joystick sensitivity |
|
||||
| 52 | | Unknown |
|
||||
| 53 | as per config | Audio messages (0: Text, 1: Speech, 2: Both) |
|
||||
| 54 | | Unknown |
|
||||
| 55 | | Unknown |
|
||||
| 56 | | Unknown |
|
||||
| 57 | | Unknown |
|
||||
| 58 | as per config | Audio channels (0: 2ch, 1: 4ch, 2: 8ch) |
|
||||
| 59 | | Unknown |
|
||||
| 60 | | Unknown |
|
||||
| 61 | | Unknown |
|
||||
| 62 | | Unknown |
|
||||
| 63 | | Unknown |
|
||||
|
||||
|
||||
The two random codes (index 31, 32) will be randomized if they are equal.
|
||||
|
||||
> The two random codes are stored in [Binary-Coded-Decimal](https://en.wikipedia.org/wiki/Binary-coded_decimal).
|
||||
|
||||
> The integer values from index 40 on seem to be all about in-game options.
|
||||
> This may be the reason why it was earlier thought that there are only 40 game variables.
|
||||
@@ -0,0 +1,80 @@
|
||||
## Archives
|
||||
This section covers the archive files. There is one template archive file, called ```archive.dat```, and a number of save-game files, called ```savgamXX.dat```. All of these files are regular resource files.
|
||||
|
||||
Any new game is based on the archive.dat file. All these archive files contain the complete game state, including the level layout. In other words: Citadel itself, with all its content, is represented through such a file; Properties and media for the content is in the other resource files.
|
||||
|
||||
## Map specific data
|
||||
Each level has 98 resources reserved, but only 51 in use. The level-specific resources are grouped according to the level identifier. For example, on Citadel level R, the resources start with ID ```4002``` (decimal) up to ```4053```. Level 1 uses ```4102``` to ```4153``` and so forth.
|
||||
|
||||
On the following pages, resources identified as ```LXX``` refer to level-specific resource ```XX``` for any level. These numbers will always be given in decimal.
|
||||
|
||||
## Extra Resources
|
||||
|
||||
### Name of archive, resource 0x0FA0 (4000)
|
||||
This resource contains the name of the archive (title of the save-game). It is a 0x00 terminated string, with a dynamic length of up to 32 bytes (including the termination character).
|
||||
|
||||
> The archive.dat file contains extra (unknown) data after the name in this resource, up to a complete length of 128 bytes. A save-game file has only the name in this resource. The name of the template archive is "Starting Game".
|
||||
|
||||
### [Game state resource 0x0FA1 (4001)](gameState.md)
|
||||
This resource contains information about the game and the hacker.
|
||||
It also contains the [level variables](levelVariables.md).
|
||||
|
||||
### Additional Resources
|
||||
|
||||
Save-game files contain 4 further resources that are not present in archive.dat :
|
||||
|
||||
* 0x0000 Unknown int32. ```0x00000000``` at first investigation
|
||||
* 0x024E Unknown.
|
||||
* 0x024F Unknown.
|
||||
* 0x0F9F Unknown int32. ```0x00004444``` at first investigation
|
||||
|
||||
## Index
|
||||
|
||||
### By topic
|
||||
* [Map Information](mapInformation.md)
|
||||
* [Level Objects](levelObjects.md)
|
||||
* [Surveillance Cameras](surveillanceCameras.md)
|
||||
* [Loop Configuration](loopConfiguration.md)
|
||||
|
||||
|
||||
### By level-specific resource ID
|
||||
* ```L02``` Map version number. int32 with value ```0x0000000B``` for all maps.
|
||||
* ```L03``` Object version number. int32 with value ```0x0000001B``` for all maps.
|
||||
* ```L04``` [Basic level information](mapInformation.md)
|
||||
* ```L05``` [Map Layout](mapInformation.md)
|
||||
* ```L06``` [Level schedules](levelSchedules.md)
|
||||
* ```L07``` [Level texture map](mapInformation.md)
|
||||
* ```L08``` [Main object table](levelObjects.md#level-object-table)
|
||||
* ```L09``` [Level object cross-reference table](levelObjects.md#level-object-cross-reference-table)
|
||||
* ```L10``` to ```L24``` 15 object [class specific tables](levelObjects.md#class-tables-and-entries)
|
||||
* ```L25``` to ```L39``` 15 object [class default info](levelObjects.md#class-default-information)
|
||||
|
||||
* ```L40``` Miscellaneous savefile version number. int32. For all maps: ```CD-Release```: ```0x0000000D```. All other: ```0x0000000B```
|
||||
* ```L41``` Unused entry. byte with value ```0x00``` for all maps.
|
||||
|
||||
* ```L42``` [Texture animation](textureAnimation.md)
|
||||
* ```L43``` [Surveillance Sources](surveillanceCameras.md)
|
||||
* ```L44``` [Surveillance Surrogates](surveillanceCameras.md)
|
||||
* ```L45``` [Level variables](levelVariables.md)
|
||||
* ```L46``` [Map notes](mapInformation.md#map-notes)
|
||||
* ```L47``` [Map notes pointer](mapInformation.md#map-notes)
|
||||
|
||||
* ```L48``` Unknown. 0x30 byte length.
|
||||
* ```L49``` Unknown. 0x1C0 byte length.
|
||||
* ```L50``` Unknown int16. ```0x0000``` for all maps.
|
||||
* ```L51``` [Loop Configuration](loopConfiguration.md)
|
||||
* ```L52``` Unknown int16. (Only present in ```CD-Release```)
|
||||
* ```L53``` Unknown. 0x40 byte length, all zeroes. (Only present in ```CD-Release```)
|
||||
|
||||
|
||||
### Levels of Citadel
|
||||
This is the level list of the base game:
|
||||
|
||||
* Level 00: Reactor level
|
||||
* Level 01-09: Levels 1-9
|
||||
* Level 10: SHODAN cyberspace
|
||||
* Level 11: Delta grove
|
||||
* Level 12: Alpha grove
|
||||
* Level 13: Beta grove
|
||||
* Level 14: Cyberspace for levels 1 and 2
|
||||
* Level 15: Cyberspace
|
||||
@@ -0,0 +1,175 @@
|
||||
## Level Objects
|
||||
|
||||
Instance data of [Level Objects](../levelObjects/index.md) is stored as part of an archive. Two resources describe general information, then further resources are object class specific.
|
||||
|
||||
### General Information
|
||||
|
||||
#### Level Object Table
|
||||
|
||||
```L08```, a compressed resource, contains a table with general entries about the objects in the current level.
|
||||
This table contains 872 entries, which houses two lists.
|
||||
|
||||
**Level Object Entry** (`Obj` struct) (27 bytes)
|
||||
|
||||
0000 byte In use flag. 0: free, 1: in use
|
||||
0001 byte Object class
|
||||
0002 byte Object subclass
|
||||
0003 int16 Class table index
|
||||
0005 int16 Cross-Reference table index (also: used list head)
|
||||
0007 int16 Next
|
||||
0009 int16 Previous
|
||||
000B uint16 X Coordinate
|
||||
000D uint16 Y Coordinate
|
||||
000F byte Z Coordinate (height)
|
||||
0010 byte Pitch rotation (around X axis), increasing values turn upwards
|
||||
0011 byte Yaw/Heading rotation (around Z axis), increasing values turn rightwards
|
||||
0012 byte Roll/Bank rotation (around Y axis), increasing values turn rightwards
|
||||
0013 byte Physics (0xFF for unaffected, the default)
|
||||
0014 byte Object type
|
||||
0015 sint16 Hitpoints
|
||||
0017 [4]byte Extra
|
||||
|
||||
The starting point for both lists is the first entry (index zero). This entry is not in use (```In use flag``` is zero).
|
||||
|
||||
The `Cross-Reference table index` field of the starting point refers to the first object of a list of objects in use. For all object entries in use,
|
||||
their ```Previous``` and ```Next``` fields form a double-linked list, with the exception of the starting point:
|
||||
The last used object entry refers to the starting point with its ```Next``` value without being referred-to from the starting point.
|
||||
|
||||
The `Next` index of the starting point refers to the first object of a list of objects not in use.
|
||||
For all object entries not in use, their `Next` field forms a single-linked list.
|
||||
The `Previous` field of unused objects is not defined and contains arbitrary data.
|
||||
The last unused object entry refers to the starting point with its ```Next``` value.
|
||||
|
||||
If an object is placed in the world, it has the X, Y and Z coordinates set, as well as the ```Cross-Reference table index``` pointing to a corresponding entry in the cross-reference table.
|
||||
If an object was spawned by the engine without a location in the world, such as loot from corpses,
|
||||
then the ```X``` field is ```0xFFFF```, ```Y``` and ```Z``` fields are zero, and the ```Cross-Reference table index``` is zero as well.
|
||||
|
||||
The ```extra``` field is a multi-purpose field, which may hold further properties and/or state. The exact features are environment specific and may also be dependent on the classification of the object.
|
||||
|
||||
##### Global extra
|
||||
|
||||
For some objects, the ```extra``` field is dependent on the object type or class, and the field is applicable to both real world and cyberspace.
|
||||
|
||||
**Basic Extra** (4 bytes)
|
||||
|
||||
0000 byte Make Info - a general index
|
||||
0001 byte Current Frame - for animations
|
||||
0002 byte Time Remainder - for animations
|
||||
0003 byte Instance Flags - for various purposes
|
||||
|
||||
This is the layout as defined by the engine. Yet, these values may be interpreted/used specifically according to type and/or environment.
|
||||
|
||||
|
||||
**Panel Extra** (4 bytes)
|
||||
|
||||
0000 byte Panel name index; Index into cybstrng 0x0869
|
||||
0001 [3]byte Other
|
||||
|
||||
If the ```Panel name``` resolves to an unknown block or empty string, then the regular object name is displayed.
|
||||
|
||||
**Surfaces Extra* (4 bytes)
|
||||
|
||||
0000 byte Unknown
|
||||
0001 byte Bitmap Index
|
||||
0002 [2]byte Unknown
|
||||
|
||||
This is used for simple surfaces, such as icons (`7/2/1`) and paintings (`7/2/4`).
|
||||
|
||||
##### Cyberspace extra
|
||||
|
||||
In case the level is cyberspace, the ```extra``` field contains the following properties.
|
||||
|
||||
**Cyberspace Level Object Extra** (4 bytes)
|
||||
|
||||
0000 byte Other
|
||||
0001 byte ICE presence
|
||||
0002 byte Unknown
|
||||
0003 byte ICE level
|
||||
|
||||
Level objects in cyberspace can be locked by ICE (Intrusion Countermeasures Electronics). ICE need to be defeated using the drill tool before the locked object can be acquired/used. The ```ICE presence``` field determines whether ICE is present. Any value != ```0x00``` has ICE present.
|
||||
If present, the health of the ICE is determined by the health of the object.
|
||||
The ```ICE level``` then determines how aggressive and powerful the ICE is. ```0x00``` is the weakest, ```0xFF``` is the highest.
|
||||
|
||||
> Although the vanilla game uses ICE only on software objects, the engine also supports ICE on other objects, such as cyberspace exits.
|
||||
|
||||
#### Level Object Cross-Reference Table
|
||||
|
||||
```L09```, a compressed resource, is a table that links level objects and the tiles they are in. The index field in the [Tile Map Entry](mapInformation.md) refers to this table, as well as the table index field in the **Level Object Entry**. This table contains 1600 entries.
|
||||
|
||||
**Level Object Cross-Reference Entry** (10 bytes)
|
||||
|
||||
0000 int16 Tile X
|
||||
0002 int16 Tile Y
|
||||
0004 int16 Index into level object entry table
|
||||
0006 int16 Index for next object
|
||||
0008 int16 Index for next tile of same object
|
||||
|
||||
Objects can extend over several tiles. The last field points to the next reference entry about the same object, with different tile coordinates.
|
||||
This field creates a single-linked list, with the last entry pointing to the first one.
|
||||
If the object is contained within one tile only, this field points to its own entry.
|
||||
|
||||
The major coordinates of the main object entry match those of the last entry of the cross-reference list. The cross-reference list only contains the X/Y values of the tiles - not sub-tile coordinates.
|
||||
|
||||
The ```Index for next object``` field creates a single-linked list, terminating with a zero value.
|
||||
This list either refers to all objects within the same tile (if referred to from a tile), or creates a pool of unused cross-reference entries. The start of this pool is the first entry (index zero).
|
||||
Unused cross-reference entries contain arbitrary data and only the next object index field is valid.
|
||||
|
||||
### Class Specific Information
|
||||
|
||||
In the following resources, all tables have a static count of entries. Each entry has a common prefix.
|
||||
|
||||
**Level Object Prefix** (6 bytes)
|
||||
|
||||
0000 int16 Index into level object entry table
|
||||
0002 int16 Previous
|
||||
0004 int16 Next
|
||||
|
||||
The tables contain two lists each, similar to the main object table:
|
||||
The starting point is the first entry (index zero). The starting point refers to a double-linked list of used entries (via ```Next```), and a single-linked list of unused entries (via ```Previous```). Both lists are terminated by referring back to index zero.
|
||||
|
||||
The ```Index``` field of the starting point does not refer to a level object, it is the index within the same table of the last used entry. (The actual "previous" link to the double-linked list of used objects.)
|
||||
|
||||
> The sum of all possible entries is slightly higher than the total count of possible **Level Object Entries**.
|
||||
|
||||
#### Class Tables and Entries
|
||||
|
||||
The following table lists the the level resources per class type. It also lists how many entries each table contains and how big one entry is.
|
||||
The name column links to the corresponding details.
|
||||
|
||||
| Class | Level Res | Name | Entry Count | Entry Size (incl. prefix) |
|
||||
|:-----:|-------------|-------------------------------------------|-------------|---------------------------|
|
||||
| 0 | ```L10``` | [Gun][L10] | 16 | 8 |
|
||||
| 1 | ```L11``` | [Ammo][L11] | 32 | 6 |
|
||||
| 2 | ```L12``` | Physics | 32 | 40 |
|
||||
| 3 | ```L13``` | [Grenade][L13] | 32 | 12 |
|
||||
| 4 | ```L14``` | [Drug][L14] | 32 | 6 |
|
||||
| 5 | ```L15``` | [Hardware][L15] | 8 | 7 |
|
||||
| 6 | ```L16``` | [Software][L16] | 16 | 9 |
|
||||
| 7 | ```L17``` | [Big Stuff][L17] | 176 | 16 |
|
||||
| 8 | ```L18``` | [Small Stuff][L18] | 128 | 16 |
|
||||
| 9 | ```L19``` | [Fixture][L19] | 64 | 30 |
|
||||
| 10 | ```L20``` | [Door][L20] | 64 | 14 |
|
||||
| 11 | ```L21``` | Animating | 32 | 10 |
|
||||
| 12 | ```L22``` | [Trap][L22] | 160 | 28 |
|
||||
| 13 | ```L23``` | [Container][L23] | 64 | 21 |
|
||||
| 14 | ```L24``` | [Critter][L24] | 64 | 46 |
|
||||
|
||||
|
||||
[L10]: ../levelObjects/00_Gun/levelGunEntry.md
|
||||
[L11]: ../levelObjects/01_Ammo/levelAmmoEntry.md
|
||||
[L13]: ../levelObjects/03_Grenade/levelGrenadeEntry.md
|
||||
[L14]: ../levelObjects/04_Drug/levelDrugEntry.md
|
||||
[L15]: ../levelObjects/05_Hardware/levelHardwareEntry.md
|
||||
[L16]: ../levelObjects/06_Software/levelSoftwareEntry.md
|
||||
[L17]: ../levelObjects/07_BigStuff/levelBigStuffEntry.md
|
||||
[L18]: ../levelObjects/08_SmallStuff/levelSmallStuffEntry.md
|
||||
[L19]: ../levelObjects/09_Fixture/levelFixtureEntry.md
|
||||
[L20]: ../levelObjects/10_Door/levelDoorEntry.md
|
||||
[L22]: ../levelObjects/12_Trap/levelTrapEntry.md
|
||||
[L23]: ../levelObjects/13_Container/levelContainerEntry.md
|
||||
[L24]: ../levelObjects/14_Critter/levelCritterEntry.md
|
||||
|
||||
### Class Default Information
|
||||
|
||||
Each level has 15 further resources, ```L25``` to ```L39```, one for each object class. The length of these resources is the same as for one class entry of the corresponding specific entries.
|
||||
This information is used as default for creating new objects. Most of the time, all their bytes are 0x00.
|
||||
@@ -0,0 +1,119 @@
|
||||
## Level Schedules
|
||||
|
||||
```L06``` is a dynamically sized list of currently active schedules. A schedule performs some delayed action at a specific time in the future.
|
||||
It contains a number of live entries equal to the ```timer count``` field from ```L04``` [(Level Information)](mapInformation.md#Level-information).
|
||||
Unless the list is full, this list always has one extra "terminator" entry at the end.
|
||||
|
||||
**Level Schedule Entry** (`SchedEvent` struct) (8 bytes)
|
||||
|
||||
0000 int16 Timestamp, with a scale of 0x100 = 10 seconds
|
||||
0002 int16 Type
|
||||
0004 byte[4] Data
|
||||
|
||||
```Time``` specifies the timestamp accoring to in-game time. Should the level become activated (either through loading of savegame load or level transition) and the current time is beyond the trigger time, the object is immediately triggered.
|
||||
|
||||
```Type``` specifies how the schedule should be handled on timeout. ```Data``` is then type-specific.
|
||||
|
||||
> The one terminator entry is required to exist, and does not have to contain any useful information at the beginning (can be all zero).
|
||||
> The engine sorts the schedule entries according to their ```trigger time```.
|
||||
|
||||
For the schedule data, any object index refers to the main object table in the level.
|
||||
|
||||
### Schedule Type 0: Null Schedule Event
|
||||
|
||||
This event does nothing.
|
||||
|
||||
|
||||
### Schedule Type 1: Grenade Schedule Event (`GrenSchedEvent` struct)
|
||||
|
||||
**Grenade Schedule Event Data** (4 bytes)
|
||||
|
||||
0000 int16 Grenade object index
|
||||
0002 byte Unique identifier
|
||||
0003 byte Unused
|
||||
|
||||
The ```unique identifier``` must match the value from the (live) grenade object in the level to be handled.
|
||||
This event removes the grenade object on timeout.
|
||||
|
||||
|
||||
### Schedule Type 2: Explosion Schedule Event
|
||||
|
||||
This event does nothing.
|
||||
|
||||
|
||||
### Schedule Type 3: Door Schedule Event (`DoorSchedEvent` struct)
|
||||
|
||||
**Door Schedule Event Data** (4 bytes)
|
||||
|
||||
0000 int16 Object index
|
||||
0002 uint16 Unique identifier
|
||||
|
||||
If the ```object index``` references an open door, then this door will be triggered to close.
|
||||
|
||||
If the ```object index``` references a "plastiqued antenna relay", then this event causes the explosion and the special handling of these fixtures.
|
||||
|
||||
|
||||
### Schedule Type 4: Trap Schedule Event (`TrapSchedEvent` struct)
|
||||
|
||||
**Trap Schedule Event Data** (4 bytes)
|
||||
|
||||
0000 int16 Target object index
|
||||
0002 int16 Source object index
|
||||
|
||||
Triggers the ```target object``` first (without condition check).
|
||||
If ```source object``` is not -1, it is attempted next, including condition checks.
|
||||
|
||||
|
||||
### Schedule Type 5: Exposure Schedule Event
|
||||
|
||||
**Exposure Schedule Event Data** (`SchedExposeData` struct) (4 bytes)
|
||||
|
||||
0000 sint8 Damage
|
||||
0001 uint8 Type
|
||||
0002 uint8 TSecs
|
||||
0003 uint8 Count -- unused
|
||||
|
||||
This event exposes ```type``` to the hacker for half of the amount given in ```damage```. Damage values are rounded towards the greater number.
|
||||
If the calculated half is not equal to the ```damage``` value, then another event is re-scheduled with an offset of ```tSecs```.
|
||||
|
||||
> An earlier version of the engine appeared to use ```count``` as a counter towards zero, though this was replaced with the damage-halving algorithm.
|
||||
|
||||
|
||||
### Schedule Types 6, 7: Floor, Ceiling Schedule Events (`HeightSchedEvent` struct)
|
||||
|
||||
These events share the same event data and algorithm.
|
||||
|
||||
**Height Schedule Event Data** (4 bytes)
|
||||
|
||||
0000 sint8 Semaphor
|
||||
0001 sint8 Key
|
||||
0002 sint8 Steps Remaining
|
||||
0003 sint8 SFX Code -- unused
|
||||
|
||||
This event references the height transition referenced by ```semaphor``` (stored in ```L53```) which has to have given ```key``` to be valid.
|
||||
|
||||
```Steps remaining``` indicates both the direction, as well as how many further steps to take. When this counter reaches zero, movement stops.
|
||||
|
||||
|
||||
### Schedule Type 8: Light Schedule Event
|
||||
|
||||
This event has no specific data.
|
||||
|
||||
It turns off any muzzle light source and restores the state of the lamp hardware.
|
||||
|
||||
|
||||
### Schedule Type 9: Bark Schedule Event (`BarkSchedEvent` struct)
|
||||
|
||||
This event has no specific data.
|
||||
|
||||
It is scheduled by specific ```trap message``` actions (action type 22) to automatically remove the side-image after a certain time from the side-MFD.
|
||||
|
||||
|
||||
### Schedule Type 10: EMail Schedule Event (`EmailSchedEvent` struct)
|
||||
|
||||
**EMail Schedule Event Data** (4 bytes)
|
||||
|
||||
0000 sint16 Data Munge (EMail index)
|
||||
0002 byte[2] Unused
|
||||
|
||||
This event is the delayed action of ```receive email``` actions (action type 15). This event is used if the action has a delay higher than zero.
|
||||
@@ -0,0 +1,36 @@
|
||||
## Level Variables
|
||||
|
||||
```L45``` contains level variables, including environmental settings.
|
||||
|
||||
**Level Variables** (94 bytes)
|
||||
|
||||
0000 int16 Data Length. = 94
|
||||
0002 byte Mist; Unused (0x00)
|
||||
0003 byte Gravity; Unused (0x00)
|
||||
0004 byte Radiation poisoning level, in 0.5 LBP
|
||||
0005 byte Gravity, in 25% OR bio contamination level, in 0.5 LBP
|
||||
0006 byte Gravity switch. If 0, ```0005``` is bio contamination. Gravity mod otherwise.
|
||||
0007 byte Bio contamination register. Must be >1 to have contamination to register
|
||||
0008 byte Radiation register. Must be >1 to have radiation to register
|
||||
0009 uint32 Exit Time; Unused in savegame
|
||||
000D [3*27]byte 3 Automap Variables entries, for first, second, full-screen (see below)
|
||||
|
||||
|
||||
> Hazards are notified from value 0x01, but affect only starting from value 0x02 (1 LBP).
|
||||
|
||||
|
||||
**Automap Variables** (27 bytes)
|
||||
|
||||
0000 byte Initialized.
|
||||
0001 byte Zoom; 1 (farthest) .. 5 (nearest)
|
||||
0002 sint32 X-coordinate; (as fix32 value)
|
||||
0006 sint32 Y-coordinate; (as fix32 value)
|
||||
000A uint16 Unknown
|
||||
000C uint16 Unknown
|
||||
000E uint16 Follow object; The object to focus on; Always 0x0001 (hacker)
|
||||
0010 uint16 Sensor object
|
||||
0012 uint16 Note object
|
||||
0014 uint16 Flags
|
||||
0016 uint16 Available flags
|
||||
0018 byte Version ID
|
||||
0019 uint16 Sensor radius; Scan radius, in tiles and sub-tiles
|
||||
@@ -0,0 +1,24 @@
|
||||
## Loop Configuration
|
||||
|
||||
```L51``` is a table containing loop configuration. 64 entries are stored in this table, with unused entries set to 0x00.
|
||||
|
||||
> This table appears to be automatically filled by displaying objects, such as screens and the like.
|
||||
> Although ```archive.dat``` contains valid information in this table, it is rewritten by the information from the level object properties.
|
||||
|
||||
**LoopConfigEntry** (15 bytes)
|
||||
|
||||
0000 int16 Object Table Index
|
||||
0002 byte Loop type
|
||||
0003 [10]byte Unused
|
||||
000D int16 Frame time -- 0x0100 is 0.9 seconds; Default: 0x0080
|
||||
|
||||
**Loop Type**
|
||||
|
||||
0 Don't loop, stick with first frame
|
||||
1 Loop forward
|
||||
2 Play once (on finish, stick with last frame)
|
||||
3 Loop backward
|
||||
4 Loop back and forth
|
||||
5 Loop back and forth
|
||||
6 Loop back and forth
|
||||
7 Loop back and forth
|
||||
@@ -0,0 +1,252 @@
|
||||
## Map Information
|
||||
|
||||
### Map layout
|
||||
|
||||
#### Level information
|
||||
|
||||
```L04```, a compressed resource, contains the basic information about a level (a map).
|
||||
|
||||
> In the original source, this structure is called ```FullMap```.
|
||||
|
||||
**Level Information** (58 bytes)
|
||||
|
||||
0000 sint32 X Size - always 64 in the archives.
|
||||
0004 sint32 Y Size - always 64 in the archives.
|
||||
0008 sint32 X Shift - always 6 in the archives.
|
||||
000C sint32 Y Shift - always 6 in the archives.
|
||||
0010 sint32 Z Shift
|
||||
0014 byte[4] Placeholder - ignore
|
||||
0018 byte Cyberspace flag. 0: real life, 1: cyberspace
|
||||
0019 byte[12] Unused
|
||||
0025 byte[21] Scheduler Info
|
||||
|
||||
> The engine doesn't support maps with more than 4096 tiles. By default, this is a map of 64x64 tiles.
|
||||
> While other combinations of X/Y sizes are feasible, as long as the respective shift parameter matches, there is
|
||||
> hardly a point to try something different than 64x64.
|
||||
|
||||
The ```z shift``` determines the height of the level as well as the size of one height unit for tiles.
|
||||
The level is one tile width high (perfect cube) if the shift value is 5.
|
||||
A shift value of 0 gives 32 tiles of height, a value of 7 one fourth (1/4) of a tile. So it's 32, 16, 8, 4, 2, 1, 1/2, 1/4 for 0..7.
|
||||
> Most levels have a shift value of 3, giving 4 tile widths of height. Security (Level 8) has a shift value of 1 - 16 tiles.
|
||||
|
||||
One height unit is the 32th of the level height. The higher the level is, the larger are the visible jumps of any height value.
|
||||
|
||||
Although any level can be marked as cyberspace - even the starting level - only levels 10, 14 and 15 properly work.
|
||||
This is due to the engine considering 10 and everything above 13 to be cyberspace.
|
||||
Cyberspace items in other levels don't work as expected, especially the exit port either crashes the game or puts the player at the start of the cyberspace level again.
|
||||
|
||||
As a further hardcoded limitation, only cyberspace levels 14 and 15 have a time limit. Level 10 is without limit.
|
||||
|
||||
The ```placeholder``` has no use in the archives. In the engine, this field is used as a placeholder for a pointer within the game logic.
|
||||
|
||||
The ```schedule``` information is the primary entry for level-specific timers.
|
||||
|
||||
|
||||
**Level Scheduler Information** (21 bytes)
|
||||
|
||||
0000 sint32 Size - always 64 in the archives
|
||||
0004 sint32 Schedule count
|
||||
0008 sint32 Element size - always 8 in the archives
|
||||
000C byte Grow - always 0 in the archives
|
||||
000D byte[4] Pointer1
|
||||
0011 byte[4] Pointer2
|
||||
|
||||
|
||||
```Size``` and ```element size``` require to be set to the values ```0x40``` and ```0x08``` respectively. Otherwise the level timers (stored in ```L06```) will not work properly.
|
||||
|
||||
The ```element size``` of 8 comes from the size of scheduler entries.
|
||||
|
||||
```Grow```, a boolean, would indicate to the scheduler system to allow reallocating the timer list to contain more than ```size``` amount of entries. Yet, the engine always initializes this with 0 (= don't grow).
|
||||
|
||||
The two pointer fields are used engine-internally.
|
||||
|
||||
|
||||
#### Tile map
|
||||
|
||||
The tiles are described in the compressed resource ```L05```, a table of tile map entries. The first entry describes the lower left tile and the next entries go east first, then north (first columns, then rows). All levels have a size of 64x64 tiles as the engine supports (and expects) only this layout.
|
||||
|
||||
The outermost tiles of the level (the 'border') should always be solid tiles. If these tiles are non-solid, the graphics engine may have rendering issues (walls not shown, just black) and entering these tiles freezes the game. This gives an effective available space of 62x62 tiles.
|
||||
|
||||
**Tile Map Entry** (16 bytes)
|
||||
|
||||
0000 byte Type
|
||||
0001 byte Floor Info
|
||||
0002 byte Ceiling Info
|
||||
0003 byte Slope height. Valid for any non-flat tile.
|
||||
0004 sint16 Index to first object in cross-reference table.
|
||||
0006 uint16 Texture Info
|
||||
0008 uint32 Flags
|
||||
000C byte Sub Clip -- always 0xFF
|
||||
000D byte Clear Solid -- unknown
|
||||
000E byte Unused
|
||||
000F byte Light delta
|
||||
|
||||
**Type** (1 byte)
|
||||
|
||||
The type is an enumeration with the following constants:
|
||||
|
||||
0x00 solid
|
||||
0x01 open
|
||||
0x02 diagonal open s/e (nw edge closed off)
|
||||
0x03 diagonal open s/w (ne edge closed off)
|
||||
0x04 diagonal open n/w (se edge closed off)
|
||||
0x05 diagonal open n/e (sw edge closed off)
|
||||
0x06 slope s->n
|
||||
0x07 slope w->e
|
||||
0x08 slope n->s
|
||||
0x09 slope e->w
|
||||
0x0A valley se->nw
|
||||
0x0B valley sw->ne
|
||||
0x0C valley nw->se
|
||||
0x0D valley ne->sw
|
||||
0x0E ridge nw->se
|
||||
0x0F ridge ne->sw
|
||||
0x10 ridge se->nw
|
||||
0x11 ridge sw->ne
|
||||
|
||||
All non-open tiles are given as low -> high. Valleys have 3 vertexes higher and one lower (at floor level). Ridges have one vertex higher and the remaining three at floor level. The given direction is that between the one vertex and its opposite one.
|
||||
|
||||
|
||||
**Floor/Ceiling Info** (1 byte)
|
||||
|
||||
bits 0-4 Height (ceiling is units down from 0x20)
|
||||
bits 5-6 Texture rotation. When viewed from above: 1: 90°, 2: 180°, 3: 270° - always clockwise
|
||||
bit 7 Hazard flag. Floor has biohazard, ceiling has radiation hazard.
|
||||
|
||||
The exact behaviour for the hazard flags is determined by the [level variables](levelVariables.md).
|
||||
|
||||
**Texture Info** (2 bytes)
|
||||
|
||||
The texture info field contains information for the tile textures of the level.
|
||||
For real world, it contains index values into the texture map (see next resource below).
|
||||
Cyberspace levels specify the palette color index for floor and ceiling of the South-Western corner.
|
||||
|
||||
Real World:
|
||||
bits 0-5 Wall texture
|
||||
bits 6-10 Ceiling texture
|
||||
bits 11-15 Floor texture
|
||||
|
||||
Cyberspace:
|
||||
bits 0-7 Floor palette index
|
||||
bits 8-15 Ceiling palette index
|
||||
|
||||
**Flags** (4 bytes)
|
||||
|
||||
Real World:
|
||||
0x80000000 Tile visited (automapper)
|
||||
0x70000000 Unused
|
||||
0x0F000000 Ceiling shadow
|
||||
0x00F00000 Unused
|
||||
0x000F0000 Floor shadow
|
||||
0x0000E000 Music index
|
||||
0x00001000 Music "peril"
|
||||
0x00000C00 Slope control. See below.
|
||||
0x00000200 Deconstructed flag ("spooky" music)
|
||||
0x00000100 Use wall texture from adjacent tile
|
||||
0x00000080 Unused -- only set for computer room on level 7
|
||||
0x00000040 Flip wall texture horizontally alternating
|
||||
0x00000020 Flip wall texture horizontally
|
||||
0x0000001F Offset for wall textures
|
||||
|
||||
Cyberspace:
|
||||
0x01000000 Flight pull: Strong pull towards floor
|
||||
0x000F0000 Flight pull
|
||||
0x0000E000 Music index
|
||||
0x00001000 Music "peril"
|
||||
0x00000C00 Slope control. See below.
|
||||
0x00000060 Game-Of-Life flags (either needs to be set)
|
||||
|
||||
|
||||
```Ceiling shadow``` and ```Floor shadow``` specify the darkness intensity for the south-western corner of the tile.
|
||||
The ceiling value darkens all four surrounding ceilings.
|
||||
The walls made by surrounding top-pillars are darkened starting from the ceiling.
|
||||
The walls made by surrounding bottom-pillars are darkened starting from their floor.
|
||||
|
||||
The floor value darkens all four surrounding floors.
|
||||
The walls made by surrounding bottom-pillars are darkened starting from the floor.
|
||||
The walls made by surrounding top-pillars are darkened starting from their ceiling.
|
||||
|
||||
> The actions to modify the light values can only give tiles more light, or remove previously added light.
|
||||
> Thus, with shadow values of 0, these tiles are as bright as possible, without any chance of making them darker.
|
||||
|
||||
|
||||
```Slope control``` specifies for the floor and ceiling how slopes (and valleys and ridges) should look like.
|
||||
|
||||
0: Ceiling is inverted to floor; A slope height of 0x1F will have ceiling and floor seal of the tile.
|
||||
1: Ceiling is mirroring the floor; A slope height of 0x10 will have their most extent vertexes touch each other.
|
||||
2: Ceiling is flat.
|
||||
3: Floor is flat.
|
||||
|
||||
|
||||
```Flip wall texture horizontally```
|
||||
|
||||
Wall textures can be flipped horizontally.
|
||||
|
||||
In the ```alternating``` case, flipping is based on the parities of the tile's two coordinates (even/odd status of the X and Y values).
|
||||
Furthermore, North/South wall textures are flipped separately to East/West wall textures; If the North/South walls are flipped for a certain tile, the corresponding East/West walls will not be flipped. If the North/South walls are not flipped, then the East/West walls will be flipped.
|
||||
> This ensures mirrored patterns are kept across corners without the need to change the flags for every other tile. This is heavily used on level 9 for the infested walls.
|
||||
|
||||
The North/South texture is to be flipped if the parities of the tile's two coordinates are different - East/West would be normal in this case.
|
||||
|
||||
The North/Shouth texture is normal if the parities of the tile's two coordinates match - East/West would be flipped in this case.
|
||||
|
||||
This alternation is inverted if additionally bit ```0x00000020```` is set.
|
||||
|
||||
|
||||
```Flight pull``` specifies what default translation/rotation forces are in play
|
||||
|
||||
0: None
|
||||
1: Weak pull towards East
|
||||
2: Weak pull towards West
|
||||
3: Weak pull towards North
|
||||
4: Weak pull towards South
|
||||
5: Medium pull towards East
|
||||
6: Medium pull towards West
|
||||
7: Medium pull towards North
|
||||
8: Medium pull towards South
|
||||
9: Strong pull towards East
|
||||
10: Strong pull towards West
|
||||
11: Strong pull towards North
|
||||
12: Strong pull towards South
|
||||
13: Medium pull towards ceiling
|
||||
14: Medium pull towards floor
|
||||
15: Strong pull towards ceiling
|
||||
16: Strong pull towards floor (requires separate extra bit)
|
||||
|
||||
> The engine applies the force to the 'nose' of the hacker, i.e. it will pull the heading until the hacker looks straight
|
||||
> at the origin of the force. This causes the implicit rotation. Only if the heading is exactly opposite to the origin,
|
||||
> then no rotation happens (i.e., pulled backwards).
|
||||
> All but the 'Strong' pulls can be countered.
|
||||
|
||||
**Light delta** (1 byte)
|
||||
|
||||
The high nibble specifies the light delta to the ceiling shadow. The low nibble specifies the light delta to the floor shadow.
|
||||
The [Change lighting action](../levelObjects/Actions.md#action-type-7-change-lightning) modifies these values.
|
||||
|
||||
|
||||
### Texture map
|
||||
|
||||
This resource is a list of int16 texture identifier in resource ```L07``` with a fixed length of 108 bytes.
|
||||
The ```Texture Info``` fields in the tile map refer to these identifier.
|
||||
Although the field for wall textures would allow for 64 textures, the resource can only hold up to 54 textures.
|
||||
The first 32 textures can be used for floor/ceiling as well.
|
||||
|
||||
> The engine caches these textures when reloading a savegame with the same level.
|
||||
> In the original source this list is also referred to as ```loaded textures``` or ```loved_textures```.
|
||||
> The 'texture' index for space is 0x00CD, the observation grating has 0x00B1 (ceiling on groves and bridge)
|
||||
|
||||
See [Level Textures](../content/LevelTextures.md) for further information.
|
||||
|
||||
|
||||
### Map notes
|
||||
|
||||
#### Text Data
|
||||
|
||||
Text for the map notes is stored in the level-specific resource ```L46```. The notes are stored sequentially, with the 0x00 character terminating a note.
|
||||
|
||||
The maximum length of one note is 40 bytes (including the termination character). The resource itself is pre-initialized with 0x00 bytes to a total length of 0x800 bytes.
|
||||
|
||||
Data in this resource is always defragmented. If a note is modified or removed, the notes are rearranged.
|
||||
|
||||
#### Next available space
|
||||
Resource ```L47``` is a single uint32 offset, pointing to the first available byte in the text data resource.
|
||||
@@ -0,0 +1,28 @@
|
||||
## Surveillance Cameras
|
||||
|
||||
The engine supports up to 8 surveillance cameras per level.
|
||||
Such a camera can be any object in the level, and an additional surrogate can determine when a linked screen should show static although the actual source would still be available.
|
||||
|
||||
|
||||
### Surveillance Sources
|
||||
|
||||
The sources of surveillance screens are defined with ```L43```. This resource contains a list of up to 8 object table index values.
|
||||
These referred objects provide the location and orientation for the video source of a screen. A screen then refers to one of these entries by using one of the corresponding [special values as 'picture source'](../levelObjects/07_BigStuff/levelBigStuffEntry.md).
|
||||
|
||||
**Surveillance Sources Table** (16 bytes)
|
||||
|
||||
0000 [8]int16 Source object table index
|
||||
|
||||
> For a source that is not an actual camera object, it is typical to find 'null' trigger objects to be the reference.
|
||||
> Unused surveillance sources refer to the unused object at index 0.
|
||||
|
||||
|
||||
### Surveillance Surrogates
|
||||
|
||||
Screens may be bound to a destructible object. If this surrogate is destroyed, the corresponding screen shows static. These associations are stored in ```L44```, a resource with a list of up to 8 object table index values.
|
||||
|
||||
**Surveillance Surrogates Table** (16 bytes)
|
||||
|
||||
0000 [8]int16 Deathwatch object table index
|
||||
|
||||
> For camera sources, it is typical to refer to the actual camera in this table.
|
||||
@@ -0,0 +1,30 @@
|
||||
## Texture Animation
|
||||
|
||||
```L42``` is a table containing animation information for textures. 4 entries are stored in this table.
|
||||
|
||||
The ```Animation Group``` field of the [Texture Properties](../fileFormat/PropertyFiles#properties-entry) specifies
|
||||
the index into this table. A wall that has such a texture set will use further textures. According to the
|
||||
```Number of frames``` field of this table entry, more textures are used from the [Texture Map](mapInformation.md#texture-map).
|
||||
|
||||
Meaning, if the level uses texture X which has an animation group set, the corresponding animation entry specifies
|
||||
how many further textures are used for this animation. These then have all to be next to each other in the texture map.
|
||||
|
||||
The properties of the first texture determine how the remaining will behave (climbable, ...)
|
||||
|
||||
> Since most textures have their animation group set to 0x00 and have no animation, the first entry in this
|
||||
> table is unused and the bytes always 0.
|
||||
|
||||
**Animation Entry** (7 bytes)
|
||||
|
||||
0000 int16 Frame time (in milliseconds)
|
||||
0002 int16 Current frame time
|
||||
0004 byte Current frame index
|
||||
0005 byte Number of frames for loop
|
||||
0006 byte Loop type/Loop state
|
||||
|
||||
**Loop Type** (1 byte)
|
||||
|
||||
0x00 Loop forward
|
||||
0x01 Loop forth-and-back (forward state)
|
||||
0x81 Loop forth-and-back (backward state)
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
## Access Levels
|
||||
|
||||
Doors can be restricted to certain access levels. The engine knows about 32 access levels (0..31).
|
||||
|
||||
The names of the access levels are stored as [texts](../media/Texts.md) in resource ```0x0879```. Per access level there
|
||||
are two text strings, so 64 in total. The first string is the short name, for example ```STD``` and the second the long
|
||||
name, ```Standard```.
|
||||
|
||||
The first level (0) with name ```None``` is not checked. Doors with level 0 immediately open.
|
||||
@@ -0,0 +1,57 @@
|
||||
## Electronic Messages
|
||||
|
||||
This chapter documents the electronic messages that the hacker receives either through triggers or collecting them.
|
||||
This means e-mails (including video mails), logs and data fragments - everything the "Multimedia data reader" can show.
|
||||
|
||||
### Text Format
|
||||
|
||||
The [text resources](../media/Texts.md#electronic-messages) for the messages contain both the content, as well as the
|
||||
meta information, encoded in text form. Any such message resource has the following string blocks:
|
||||
|
||||
1 line Meta info
|
||||
1 line Title
|
||||
1 line Sender
|
||||
1 line Subject
|
||||
N lines Verbose text
|
||||
1 line Empty
|
||||
M lines Terse text
|
||||
1 line Empty
|
||||
|
||||
The ```Meta info``` line describes what to show additionally. This text has the following format:
|
||||
|
||||
meta-info := [event " "] [color " "] [left-mfd] ["," [" "] right-mfd]
|
||||
event := ("i" hex2) | "t"
|
||||
color := "c" hex2
|
||||
left-mfd := dec
|
||||
right-mfd := dec
|
||||
|
||||
Examples:
|
||||
"13, 18"
|
||||
"i17 8"
|
||||
"t cD1 23,23"
|
||||
"cD1 23,6"
|
||||
|
||||
|
||||
For most of the messages, at least ```left-mfd``` is specified. ```left-mfd``` and ```right-mfd``` are decimal offset
|
||||
numbers that refer to the image to show in the respective MFD. The offset is based on resource ```0x0028```.
|
||||
If ```left-mfd``` is greater or equal 256, then the message refers to a video mail. Video mails don't have an MFD image.
|
||||
|
||||
If specified, the ```color``` field identifies a hexadecimal colour palette index. This colour is used to draw the sender and subject lines.
|
||||
|
||||
The ```event``` field chains messages together. "i" events identify the message that must immediately follow the current one;
|
||||
The hexadecimal number is the offset for the next message (based on resource ```0x0989```). Such interrupt messages then have "t" as event.
|
||||
|
||||
> The vanilla resource files contain a few messages with errors in them:
|
||||
> There are some "stub email" messages with empty header lines, the text "stub email" twice and only one terminating empty line.
|
||||
> Furthermore, there is one message in ```gerstrng.res``` which misses the terminating empty line in the terse text.
|
||||
|
||||
### Text Content
|
||||
|
||||
Within the texts, the substring ```$N``` is the placeholder for the name of the hacker.
|
||||
|
||||
### Audio
|
||||
|
||||
Corresponding audio resources are based on ID ```0x0AB5```. If an electronic message with ID X has audio, the audio will have resource ID ```0x0AB5``` + X. (Also: resource ID of text resource + 300)
|
||||
|
||||
These audio resources are [MOVI resources](../media/moviResources.md) with only the audio component. The audio recordings are stored in the files
|
||||
```citalog.res``` (English), ```geralog.res``` (German) and ```frnalog.res``` (French).
|
||||
@@ -0,0 +1,29 @@
|
||||
## Level Textures
|
||||
|
||||
A level texture is a square bitmap used for level paneling - floors, ceiling and walls. The resources contain 273 textures,
|
||||
for which there are four different resolutions available.
|
||||
|
||||
### Bitmaps
|
||||
|
||||
The bitmaps are stored uncompressed in ```texture.res``` in the following resources:
|
||||
|
||||
0x004C 16x16 bitmaps, one per block (a compound resource)
|
||||
0x004D 32x32 bitmaps, one per block (a compound resource)
|
||||
0x02C3 - 0x03D3 64x64 bitmaps, one per resource
|
||||
0x03E8 - 0x04F8 128x128 bitmaps, one per resource
|
||||
|
||||
### Texts
|
||||
|
||||
Each texture comes with a description (name) and a "can't be used" message. [These texts](../media/Texts.md)
|
||||
are stored in resources ```0x086A``` and ```0x086B``` respectively.
|
||||
|
||||
> Note: The text resources reserve 512 blocks, but only 273 are used.
|
||||
|
||||
### Properties
|
||||
|
||||
The [texture properties](../fileFormat/PropertyFiles#texture-Properties-textprop.dat) give further information on textures.
|
||||
|
||||
### Animation
|
||||
|
||||
Some textures, according to their properties, are in animation groups. These groups are controlled [per level](../archives/textureAnimation.md).
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
## Conventions
|
||||
|
||||
### Content
|
||||
Information in these documents MUST be verifiable, or have been verified (e.g. through testing or cross-reference to original code) to be included. Assumptions, contradictions, discussions and the like MUST be handled through the [issue](https://github.com/inkyblackness/ss-specs/issues) system.
|
||||
|
||||
In general, changes to the documents SHOULD be introduced by linking commits to corresponding issues. This way, issues can be used as reference material for verification.
|
||||
|
||||
### Language
|
||||
The human language of this documentation is English. Names of types/fields SHOULD follow that of the source (which is presumably en-us), while prose text SHOULD follow en-uk .
|
||||
|
||||
This is primarily to uphold the legacy of this documentation. The original ss-specs was maintained within the context of TSSHP, which came from Britain.
|
||||
|
||||
When wording actions, consider differenciating between the character in the game-world ("the hacker"), and the player. ("The hacker has a rotation angle of xyz, so the player sees...").
|
||||
|
||||
Sentences referring to individuals SHALL be phrased with inclusive, gender neutral language. The use of [singular they](https://en.wikipedia.org/wiki/Singular_they) is to be used if no other option is available.
|
||||
|
||||
> While the hacker is represented with a male body and voice in the original game, a fan-mod could change this. (see [here](https://www.moddb.com/mods/system-shock-female-hacker))
|
||||
> This documentation states raw engine data, which doesn't care about humans, even if considered to be insects.
|
||||
|
||||
More generally, consider online guides about inclusive language, such as [this one from Google](https://developers.google.com/style/inclusive-documentation).
|
||||
|
||||
### Formatting
|
||||
|
||||
Vanilla [Markdown](http://daringfireball.net/projects/markdown/syntax) SHOULD be used for all pages.
|
||||
|
||||
The biggest header available is the H2 header (""## Title"). H1 header are reserved for the main title. Each page SHOULD start with an H2 header, which is also the link in the [index](index.md).
|
||||
|
||||
|
||||
### Data
|
||||
In general, this documentation describes (serialized) data structures. Such data structures SHOULD be documented using code blocks and follow the following format:
|
||||
|
||||
offset type description
|
||||
|
||||
|
||||
#### Example
|
||||
|
||||
0000 int32 some value
|
||||
0004 [14]byte unknown, not used (0x00)
|
||||
0012 int16 other value
|
||||
|
||||
Offset values MUST start at 0 and be given in hexadecimal (or placeholder). They SHOULD have a width of 4 (or more) digits.
|
||||
|
||||
Types are field specific.
|
||||
|
||||
Description is a short human-readable text describing the field.
|
||||
|
||||
#### Integers
|
||||
|
||||
For integer types, they MUST be given in the following format:
|
||||
|
||||
(s|u)?int(8|16|24|32)
|
||||
|
||||
's' and 'u' prefixes specify 'signed' and 'unsigned integer' respectively. If no sign-prefix is given, it has not been verified whether this field allows negative values or allows greater positive values.
|
||||
|
||||
Implementors MAY treat fields without known sign to be unsigned - this can be the case for length fields for instance. It is unknown whether the original executable would handle them correctly.
|
||||
|
||||
Unless otherwise noted, integer values are stored in [little-endian](http://en.wikipedia.org/wiki/Endianness#Little-endian) format.
|
||||
|
||||
#### Fixed point numbers
|
||||
|
||||
Due hardware limitations and slow perfomance of float point operations, System Shock uses fixed point number represenation of real data type.
|
||||
Usually engine uses [Q15.16](https://en.wikipedia.org/wiki/Q_(number_format)) format (1 bit for sign, 15 bits for integer part, 16 bits for fractional):
|
||||
|
||||
0x 0000 0000
|
||||
| |
|
||||
| fractional part
|
||||
integer part with sign (first bit, 0 means positive, 1 - negative)
|
||||
|
||||
This format is refered as `fix` (int32). For example, (2 * Pi) number is `0x0006487f` (6 + 18559/65536 = 6.28319)
|
||||
|
||||
Internally engine supports Q23.8 numbers (`fix24`) or even Q2.28 (for some 2D- and 3D-computations).
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
## Property Files
|
||||
A few files don't have an archive format, and instead are flat files consisting directly serialized tables.
|
||||
|
||||
### Texture Properties (textprop.dat)
|
||||
This file contains a single table of texture property entries, after a header.
|
||||
|
||||
> The table appears to be truncated. Since the game only uses 273 textures, this may have never been detected.
|
||||
> The file has 4004 bytes on disk, meaning 4000 bytes are available for the table.
|
||||
> In a test, the original engine appeared to be fine to read a smaller file with exactly 273 entries (3007 bytes) -
|
||||
> which had the unknown fields set to zero.
|
||||
|
||||
> The original source explains the difference: The texture property system would support up to 400 textures.
|
||||
> It also **assumed** a property structure size of 10 bytes (hardcoded value), while the actual structure is 11 bytes long.
|
||||
> In other words, one could feed the engine more than 273 textures, yet no more than 363. More than 363 would simply be ignored and the extra textures would just have their default properties.
|
||||
> This also explains why the Mac port reads exactly 363 textures, as reading more would exhaust the file.
|
||||
|
||||
|
||||
#### Header
|
||||
The file starts with a 4-byte header.
|
||||
|
||||
**Texture Properties File Header** (4 bytes)
|
||||
|
||||
0000 int32 file version number, value 0x09
|
||||
|
||||
|
||||
The engine rejects a properties file with a different version number.
|
||||
|
||||
|
||||
#### Properties Entry
|
||||
|
||||
**Texture Property Entry** (11 bytes)
|
||||
|
||||
0000 byte family (unused)
|
||||
0001 byte target (unused)
|
||||
0002 sint16 resilience (unused); Default: 10
|
||||
0004 sint16 distance modifier; Default: 0
|
||||
0006 byte Climbable. 0x00: not climbable; != 0x00: wall can be climbed (original name: friction)
|
||||
0007 byte friction walk (unused); Always 0x00
|
||||
0008 byte Transparency control (original name: force_dir)
|
||||
0009 byte Animation group
|
||||
000A byte Animation index - if texture is animated
|
||||
|
||||
The two bytes at the beginning (`family` and `target`) almost always are each set to the low-byte of the index. A few exceptions have both bytes 0x00. Since they are unused, it is unclear what they mean.
|
||||
|
||||
The `resilience` is nearly always `0x0A`; The one existing exception has it 0. Since it is unused, it is unclear what it means.
|
||||
|
||||
The `distance modifier` always zero. It is used in the renderer to determine which texture resolution to use, based on distance from the camera. A higher modifier causes the smaller resolutions to be chosen at larger distances; A negative value causes an earlier switch.
|
||||
|
||||
See [Texture Animation](../archives/textureAnimation.md) for details on animated textures.
|
||||
|
||||
**Transparency Control**
|
||||
|
||||
0x00 Regular texture; transparent pixel (palette index 0x00) are drawn black
|
||||
0x01 Space texture (pixel data of image is ignored)
|
||||
0x02 Texture with space background for transparent pixels
|
||||
|
||||
|
||||
### Object Properties (objprop.dat)
|
||||
The object properties file contains several tables about properties of [level objects](../levelObjects/index.md). It has the following format:
|
||||
|
||||
| Header | Class 0 Tables | Class 1 Tables | ... | Common Table |
|
||||
|
||||
#### Header
|
||||
The file starts with a 4-byte header containing the version number.
|
||||
|
||||
**Object Properties File Header** (4 bytes)
|
||||
|
||||
0000 int32 file version number, value 0x2D
|
||||
|
||||
|
||||
The engine rejects a properties file with a different version number.
|
||||
|
||||
#### Class Tables
|
||||
For each object class, one entry exists with a table of class-generic properties and a further table, subclass-specific:
|
||||
|
||||
| Class N Tables |
|
||||
| Generic | Subclass 0 | Subclass 1 | ... | Subclass N |
|
||||
|
||||
The sizes of the generic and specific tables are dependent on the object class, subclass and type amount.
|
||||
The generic table contains one entry per object type of this class. The specific tables contain one entry per object type of the subclass.
|
||||
|
||||
See [Level Objects](../levelObjects/index.md) for an overview of the amount of types and their entry sizes.
|
||||
|
||||
|
||||
#### Common Table
|
||||
At the end of the file is the table with common properties. For each object type one entry.
|
||||
|
||||
**Common Object Properties** (27 bytes)
|
||||
|
||||
0000 int32 Mass
|
||||
0004 int16 Default hitpoints
|
||||
0006 uint8 Armour
|
||||
0007 byte Render type
|
||||
0008 byte Physics type; 0x00: none (insubstantial), 0x01: regular, 0x02: special
|
||||
0009 byte Hardness; 0..253
|
||||
000A byte Unused; Internally called "pep", this value appears to not be used by the engine.
|
||||
000B byte Physics XR; 0..253
|
||||
000C byte Unused; Internally called "physics_y". These values are set (almost) identical to 000B and have no effect.
|
||||
000D byte Physics Z; Set to 0x30 for all barriers (10/x/x).
|
||||
000E byte Vulnerabilities
|
||||
000F byte Special vulnerabilities
|
||||
0010 [2]byte Unused
|
||||
0012 byte Defence value
|
||||
0013 byte Toughness; 0x03: Invincible
|
||||
0014 int16 Flags
|
||||
0016 int16 MFD/Mesh ID
|
||||
0018 [2]byte Bitmap 3D field model index
|
||||
001A byte Destruction effect
|
||||
|
||||
|
||||
`Physics type` governs how collisions shall be handled. `0x00` makes the object insubstantial, ignoring forces applied to it. For instance, most scenery stays where it was put. `0x01` is for regular objects meant to react "normal" in a physical world. `0x02` behaves strange is set for exactly one object (`14/0/6`, "SONIC THE HEDGEHOG", an unused critter). Objects with a physics type of `0x02` aren't affected by gravity for instance, but are repelled if hacker runs into them.
|
||||
The `hardness` acts as repulsion force on the object if it collides with the ground or walls - or on the hacker if hacker runs into it.
|
||||
Hardness depends on the `mass`; Objects with more mass bounce around less.
|
||||
|
||||
The `physics xr` value is applied to vertically center (animated) sprites on their position. If `0x00`, the sprites are rendered with their bottom anchored at the object's position. Higher values will move the sprites downwards.
|
||||
|
||||
Related, the `physics z` value is inconsistently used as a height value. Only if this value is `0x00` (most of the time), then `physics xr` is used for height calculation. Still, the XR value is used far more often than the Z value.
|
||||
|
||||
The `vulnerabilities` and `special vulnerabilities` match the corresponding damage type fields from [Generic Weapon Info](../levelObjects/GenericWeaponInfo.md).
|
||||
> The engine, internally, calls this field `resistances`, yet the code does the opposite. Furthermore, this `resistances` field covers the four bytes from `000E`.
|
||||
|
||||
The field of `special vulnerabilities` is split up into `0x0F` primary vulnerabilities (double damage) and `0xF0` super vulnerabilities (quad damage). Damage is multiplied only if the originating special force equals the vulnerabilities in these fields.
|
||||
> Quad damage is reduced to triple damage on difficulty level 3 (either for real-world, or cyber, wherever it is calculated).
|
||||
|
||||
The `defence value` is compared to the `offence value` of a weapon or projectile to determine a "critical hit" (or critical reduction). Higher defence values will decrease the damage, higher offence values will increase the damage. If it is `0xFF`, then the target is invulnerable to critical hits.
|
||||
|
||||
The `toughness` determines how much damage, after most of the calculation, goes through - this still requires the object to be solid to register damage. The value of `0x03` reduces the damage to zero. Otherwise, this value is considered to be a shift factor, so a value of `0x01` halves damage, `0x02` quarters it.
|
||||
> This value is set to `0x04` only for the non-used SHODAN critter `14/3/5`. This one would have been affected by only the strongest weapons.
|
||||
> Probably this value was intended to be in range of 0..3 only.
|
||||
|
||||
`MFD/Mesh ID` identifies the MFD to open for this type of object, if selected from inventory. For 3D objects in the world, this value identifies the 3D mesh to render, based on resource `0x08FC`.
|
||||
|
||||
|
||||
**Render Type Enumeration** (1 byte)
|
||||
|
||||
0x01 3D object
|
||||
0x02 Sprite
|
||||
0x03 Screen
|
||||
0x04 Critter
|
||||
0x06 Fragments (e.g. the Cyberdog)
|
||||
0x07 Not drawn
|
||||
0x08 Oriented surface (door, wall decoration)
|
||||
0x0B Special
|
||||
0x0C Force door
|
||||
|
||||
|
||||
**Common Object Flags** (2 byte)
|
||||
|
||||
0x0001 Useful inventory object (green font)
|
||||
0x0002 Solid - can't be passed through
|
||||
0x000C Use mode (see below)
|
||||
0x0010 Usable inventory object - object is triggered on double-click in inventory list
|
||||
0x0020 Blocks 3D rendering if closed (set for opaque doors)
|
||||
0x00C0 Light type (see below)
|
||||
0x0100 Solid if closed (set for barriers and repulsor object)
|
||||
0x0200 Flat solid (objects can be placed on it)
|
||||
0x0400 Doubled bitmap size (set for various explosion animations)
|
||||
0x0800 Destroy on contact
|
||||
0x7000 Class-specific flags
|
||||
0x8000 Useless object. Unless specifically marked useful otherwise, object can be removed to make room
|
||||
|
||||
**Use Mode Enumeration** (2 bit)
|
||||
|
||||
0x00 Pickup - items can be taken
|
||||
0x01 Use - items are used, not taken
|
||||
0x02 undefined
|
||||
0x03 "Null" - can't be used
|
||||
|
||||
**Light Type Enumeration** (2 bit)
|
||||
|
||||
0x00 Normal, simple lighting
|
||||
0x01 Complex lighting
|
||||
0x02 Ignore darkness
|
||||
0x03 Deferred light type (instance-specific)
|
||||
|
||||
|
||||
**Bitmap 3D Bitfield** (2 byte)
|
||||
|
||||
0x03FF Bitmap number low mask
|
||||
0x8000 Bitmap number high mask
|
||||
0x0400 Animation
|
||||
0x0800 Repeat
|
||||
0x7000 Frame number mask
|
||||
|
||||
|
||||
**Object Destruction Effect** (1 byte)
|
||||
|
||||
This byte is a bitmask field with the following layout:
|
||||
|
||||
0x1F Animation frame index -- refers to different types of animations
|
||||
0x20 Play destruction sound
|
||||
0x40 Play destruction sound (not used in main game)
|
||||
0x80 Actual explosion (with damage) -- requires Animation frame index to be 0x0F
|
||||
|
||||
> Some objects have their "private" destruction sounds and have none of the sound bits set.
|
||||
> The `actual explosion`, set for larger electrical appliances, works only if the full value is `0x8F`.
|
||||
@@ -0,0 +1,126 @@
|
||||
## Resource Files
|
||||
Resource files are structured archives. These files contain one or more "resource" entries. Resources are identified and contain one or more data blocks. A resource with more than one data block is called a "compound resource".
|
||||
|
||||
### Identifier
|
||||
|
||||
A resource identifier is a ```uint16``` value, and a compound resource uses a ```uint16``` value as index.
|
||||
|
||||
Resource identifier are "valid" from value ```0x0003``` and above.
|
||||
```0x0000``` is the NULL identifier (this was quick approach to erase resources from file for developers), and ```0x0001``` and ```0x0002``` are used engine-internally (first used to point to head ptr in
|
||||
[LRU](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) cache, second - to tail ptr in LRU).
|
||||
|
||||
### General Format
|
||||
A resource file consists of a header, resources and a file directory. The header points to the file offset of the file directory and the file directory points to the file offset of the first resource.
|
||||
|
||||
| /--------------------------------------v |
|
||||
| Header.dirOffset | Res0 | Res1 | ... | Res N | Directory.dataOffset |
|
||||
| ^----------------------------------------/ |
|
||||
|
||||
All resources, as well as the file directory, start at a 4-byte boundary.
|
||||
|
||||
To calculate the file offset of a resource, the file directory has to be read first to determine the offsets (and lengths) of the previous resources.
|
||||
|
||||
> Although the format would allow for a different order, all resource files have the directory at the end of the file.
|
||||
|
||||
### File Header
|
||||
The file header has a length of 128 bytes and has the following format:
|
||||
|
||||
**File Header** (`ResFileHeader` struct, 128 bytes)
|
||||
|
||||
0000 [16]byte signature signature "LG Res File v2\r\n"
|
||||
0010 [96]byte comment comment, terminated with "\x1A" (remainder 0x00)
|
||||
0070 [12]byte reserved reserved, set to 0x00
|
||||
007C sint32 dirOffset file offset to directory
|
||||
|
||||
> No resource file has been found containing a comment. It always only contains the terminator byte 0x1A.
|
||||
> The comment is terminated with 0x1A as this represents the ```Ctrl+Z``` code. This was a little trick to enable people to ```type``` the file on the command line and not be spammed with binary garbage.
|
||||
|
||||
### File Directory
|
||||
The file directory consists of a 6 byte header followed directly by its directory entries:
|
||||
|
||||
**Resource file directory header** (`ResDirHeader` struct, 6 bytes)
|
||||
|
||||
0000 uint16 numEntries number of resources in the file
|
||||
0002 sint32 dataOffset file offset to beginning of first resource
|
||||
|
||||
**Resource file directory entry** (`ResDirEntry` struct, 10 bytes)
|
||||
|
||||
0000 uint16 id resource ID
|
||||
0002 sint24 size resource length (unpacked)
|
||||
0005 sint8 flags resource flags (see below)
|
||||
0006 sint24 csize resource length (packed in file)
|
||||
0009 sint8 type resource type (see below)
|
||||
|
||||
### Resource Flags
|
||||
|
||||
The resource flag marks extra information about the resource.
|
||||
|
||||
**Resource Flag** (1 byte)
|
||||
|
||||
0x01 RDF_LZW compressed
|
||||
0x02 RDF_COMPOUND compound
|
||||
0x04 RDF_RESERVED reserved (unused)
|
||||
0x08 RDF_LOADONOPEN load on open (unused)
|
||||
|
||||
> The original source lists several more resource flags, which are all unused in System Shock.
|
||||
> Presumably this is the result of re-used code.
|
||||
|
||||
"Flat" resources contain only one data block, which is the complete resource data itself. Compound resources contain 0, one, or more blocks.
|
||||
|
||||
### Resource Types
|
||||
|
||||
The following resource types appears in System Shock:
|
||||
|
||||
0x00 UNKNOWN Palette (although originally called "unknown", it is used for palettes exclusively)
|
||||
0x01 STRING String
|
||||
0x02 IMAGE Image
|
||||
0x03 FONT Font
|
||||
0x04 ANIM Animation Script (Video clip)
|
||||
0x07 VOC Sound effects and voices (.voc)
|
||||
0x0F OBJ3D 3D model geometry
|
||||
0x11 MOVIE Movie
|
||||
0x30 APP1 Application specific resource (used in archive.dat for storing maps)
|
||||
|
||||
> The original source lists several more resource types, which are all unused in System Shock.
|
||||
> Presumably this is the result of re-used code.
|
||||
>
|
||||
> There exists 0x05 (PALL) resource type specially for palettes, but never used in System Shock.
|
||||
|
||||
### Compound Resources
|
||||
If a resource is flagged to be compound, the resource data starts with a directory. This directory contains relative offsets to the first bytes of the contained blocks, following the directory.
|
||||
|
||||
**Resource directory** (2 bytes + 4 bytes per block + 4 bytes)
|
||||
|
||||
0000 uint16 number of blocks in resource
|
||||
0002 sint32 resource offset to first block
|
||||
....
|
||||
nnnn sint32 resource offset to last block
|
||||
nnnn+4 sint32 total length of resource
|
||||
|
||||
To calculate the length of a block N, take the start offset of N+1 and subtract the start offset of N. This is why there is one extra offset entry in the directory.
|
||||
|
||||
If a compound resource is compressed, the directory itself is not compressed. Resource offsets always point into the uncompressed data.
|
||||
|
||||
> Some compound resources have two zero bytes between the directory and the first block.
|
||||
|
||||
### Resource Compression
|
||||
Resource compression is based on the [LZW algorithm](http://en.wikipedia.org/wiki/Lempel%E2%80%93Ziv%E2%80%93Welch). It uses a fixed word-size of 14 bits. Two words are reserved for control.
|
||||
|
||||
The words are serialized sequentially big-endian as a continuous stream.
|
||||
For example, if the first 7 bytes in the resource are
|
||||
|
||||
aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg
|
||||
|
||||
then the corresponding words are
|
||||
|
||||
aaaaaaaabbbbbb bbccccccccdddd ddddeeeeeeeeff ffffffgggggggg
|
||||
|
||||
with the high bit to the left in each case.
|
||||
|
||||
The first 256 words of the dictionary are initialized with length 1 for the corresponding byte values. The reserved words are:
|
||||
* 0x3FFE Reset dictionary to initial state
|
||||
* 0x3FFF End-Of-Stream
|
||||
|
||||
The End-Of-Stream marker is always issued. The serialized byte stream always contains a trailing 0x00 byte after the End-Of-Stream word.
|
||||
|
||||
The compressor issues a dictionary reset when it is exhausting the dictionary and can't add a new word to it for the 1001st time.
|
||||
@@ -0,0 +1,188 @@
|
||||
## File Overview
|
||||
### Variants
|
||||
Not considering any re-releases, System Shock 1 was available in the following variants:
|
||||
* For DOS
|
||||
* Demo: HD and CD
|
||||
* Release: HD and CD
|
||||
* For MAC
|
||||
* Release: CD
|
||||
|
||||
> Unless otherwise noted, this documentation considers only the DOS CD release.
|
||||
|
||||
The main difference between HD and CD releases is the CD releases contain audio files for the voice logs and provide a high resolution option.
|
||||
|
||||
### Locations
|
||||
Data files described in this documentation are available at the following locations:
|
||||
* CD-ROM (System Shock 1 CD)
|
||||
* /cdrom/data
|
||||
* /hd/data (will be copied to HD)
|
||||
* HD (System Shock installation directory)
|
||||
* /data
|
||||
|
||||
### File Types
|
||||
Data files come in the following variants:
|
||||
* [Resource files](ResourceFiles.md), which are structured archives
|
||||
* [Property files](PropertyFiles.md), containing one or more serialized tables
|
||||
|
||||
Resource files are the majority. All files with filename suffix `.res` are resource files. Savegame files have the same format, including the "starter" savegame file `archive.dat`. These files contain one or more "resource" entries. Resources are identified and contain one or more data blocks. A resource with more than one data block is called a "compound resource".
|
||||
|
||||
The property files are "flat" files containing one or more serialized tables.
|
||||
|
||||
### List of Files
|
||||
|
||||
The following table shows an overview of the known files, across the different releases.
|
||||
|
||||
For resource files, resources may share the same identifier. In this case they represent the alternatives available through configuration. The options are:
|
||||
* Language. Available are: "English", "French" and "German"
|
||||
* Cutscene resolution (MOVI format). Available are: "low" (320x150) and "svga" (600x300)
|
||||
|
||||
> The "bitmap" based cutscenes have a resolution of 320x200 and have their own identifier.
|
||||
|
||||
<table style="width:100%;">
|
||||
<tr>
|
||||
<th rowspan=2>Content</th>
|
||||
<th colspan=3>Languages</th><th colspan=2>Location HD Release</th><th colspan=2>Location CD Release</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ENG</th><th>FRN</th><th>GER</th>
|
||||
<th>Demo</th><th>Release</th><th>Demo</th><th>Release</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="8">Startup and Cutscenes</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Splash screens</td><td colspan=3>```splash.res```</td>
|
||||
<td>HD</td><td>HD</td><td>CD</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Splash screen palette</td><td colspan=3>```splshpal.res```</td>
|
||||
<td>--</td><td>HD</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Palette for low-res bitmap cutscenes</td><td colspan=3>```cutspal.res```</td>
|
||||
<td>--</td><td>HD</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Low-Res bitmap intro cutscene</td><td colspan=3>```start1.res```</td>
|
||||
<td>--</td><td>HD</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Low-Res MOVI intro cutscene</td><td>```lowintr.res```</td><td>```lofrintr.res```</td><td>```logeintr.res```</td>
|
||||
<td>--</td><td>--</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>High-Res MOVI intro cutscene</td><td>```svgaintr.res```</td><td>```svfrintr.res```</td><td>```svgeintr.res```</td>
|
||||
<td>--</td><td>--</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Low-Res bitmap end cutscene</td><td colspan=3>```win1.res```</td>
|
||||
<td>--</td><td>HD</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Low-Res MOVI end cutscene</td><td colspan="3">```lowend.res```</td>
|
||||
<td>--</td><td>--</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>High-Res MOVI end cutscene</td><td colspan="3">```svgaend.res```</td>
|
||||
<td>--</td><td>--</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Low-Res bitmap death cutscene</td><td colspan=3>```death.res```</td>
|
||||
<td>--</td><td>HD</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Low-Res MOVI death cutscene</td><td colspan="3">```lowdeth.res```</td>
|
||||
<td>--</td><td>--</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>High-Res MOVI death cutscene</td><td colspan="3">```svgadeth.res```</td>
|
||||
<td>--</td><td>--</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Main menu screens</td><td colspan=3>```intro.res```</td>
|
||||
<td>HD</td><td>HD</td><td>CD</td><td>HD & CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="8">In-game Resources</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>New Game Template</td><td colspan=3>```archive.dat```</td>
|
||||
<td>HD</td><td>HD</td><td>CD</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>In-game palette</td><td colspan=3>```gamepal.res```</td>
|
||||
<td>HD</td><td>HD</td><td>CD</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Texts</td><td>```cybstrng.res```</td><td>```frnstrng.res```</td><td>```gerstrng.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>HUD resources</td><td>```mfdart.res```</td><td>```mfdfrn.res```</td><td>```mfdger.res```</td>
|
||||
<td>HD 1)</td><td>HD</td><td>HD 1)</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Trigger audio</td><td>```citbark.res```</td><td>```frnbark.res```</td><td>```gerbark.res```</td>
|
||||
<td>--</td><td>--</td><td>CD 1)</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Log Audio</td><td>```citalog.res```</td><td>```frnalog.res```</td><td>```geralog.res```</td>
|
||||
<td>--</td><td>--</td><td>CD 1)</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Video Mails</td><td colspan=3>```vidmail.res```</td>
|
||||
<td>--</td><td>HD</td><td>--</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>???</td><td colspan=3>```objart.res```</td>
|
||||
<td>HD</td><td>HD</td><td>CD</td><td>CD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>???</td><td colspan=3>```objart2.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>???</td><td colspan=3>```sideart.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Level textures</td><td colspan=3>```texture.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>???</td><td colspan=3>```citmat.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sound Effects</td><td colspan=3>```digifx.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>???</td><td colspan=3>```gamescr.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>???</td><td colspan=3>```handart.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>???</td><td colspan=3>```obj3d.res```</td>
|
||||
<td>HD</td><td>HD</td><td>HD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>???</td><td colspan=3>```objart3.res```</td>
|
||||
<td>HD</td><td>HD</td><td>CD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="8">Property Files</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Object properties</td><td colspan=3>```objprop.dat```</td>
|
||||
<td>HD</td><td>HD</td><td>CD</td><td>HD</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Texture properties</td><td colspan=3>```textprop.dat```</td>
|
||||
<td>HD</td><td>HD</td><td>CD</td><td>CD</td>
|
||||
</tr>
|
||||
</table>
|
||||
1) Only the English files available
|
||||
@@ -0,0 +1,29 @@
|
||||
## Index
|
||||
|
||||
* [Conventions](conventions.md)
|
||||
|
||||
* General File Format
|
||||
* [File Overview](fileFormat/index.md)
|
||||
* [Resource Files](fileFormat/ResourceFiles.md)
|
||||
* [Property Files](fileFormat/PropertyFiles.md)
|
||||
|
||||
* Archives
|
||||
* [Archive Overview](archives/index.md)
|
||||
|
||||
* Raw Media
|
||||
* [Bitmaps](media/Bitmaps.md)
|
||||
* [Palettes](media/Palettes.md)
|
||||
* [Sound Effects](media/SoundEffects.md)
|
||||
* [MOVI Resources](media/moviResources.md)
|
||||
* [Video Clips](media/VideoClips.md)
|
||||
* [Texts](media/Texts.md)
|
||||
* [Geometry](media/Geometry.md)
|
||||
|
||||
* Content
|
||||
* [Access Levels](content/AccessLevels.md)
|
||||
* [Electronic Messages](content/ElectronicMessages.md)
|
||||
* [Level Objects](levelObjects/index.md)
|
||||
* [Level Textures](content/LevelTextures.md)
|
||||
|
||||
* Other Files
|
||||
* [Music](other/Music.md)
|
||||
@@ -0,0 +1,79 @@
|
||||
### Gun Properties
|
||||
|
||||
#### Generic Gun Properties
|
||||
|
||||
**Generic Gun Propertes** (`GunProp` struct) (2 bytes)
|
||||
|
||||
0000 uint8 Fire rate
|
||||
0001 byte Ammo type
|
||||
|
||||
For non-automatic guns, the `fire rate` specifies when the next bullet can be shot. For melee weapons it is the time until the next swing can be made.
|
||||
It is measured in game time, with a unit for this value of about 36 milliseconds. A value of ```0x00``` means 'as fast as you can press fire'.
|
||||
> Changing this value does not have any detectable effect for automatic guns (```0/1/x```).
|
||||
|
||||
|
||||
**Ammo type** (1 byte)
|
||||
|
||||
0xF0 Ammo subclass identifier
|
||||
0x0F Bitmask, which ammo types within the ammo subclass are compatible (0..3)
|
||||
|
||||
> Ammo type is ignored for beam and melee weapons.
|
||||
|
||||
|
||||
#### Specific 2 Properties
|
||||
|
||||
This subclass describes special projectile weapons.
|
||||
|
||||
**Specific 2 Properties** (`SpecialGunProp` struct) (16 bytes)
|
||||
|
||||
0000 [8]byte [Generic Weapon Info](../GenericWeaponInfo.md)
|
||||
0008 uint8 Projectile travel speed
|
||||
0009 int32 Projectile triple (0x00CCSSTT)
|
||||
000D uint8 Attack mass
|
||||
000E sint16 Attack speed (kickback)
|
||||
|
||||
|
||||
#### Specific 3 Properties
|
||||
|
||||
This subclass describes melee weapons.
|
||||
|
||||
**Specific 3 Properties** (`HandtohandGunProp` struct) (13 bytes)
|
||||
|
||||
0000 [8]byte [Generic Weapon Info](../GenericWeaponInfo.md)
|
||||
0008 uint8 Energy usage
|
||||
0009 uint8 Attack mass (impact force - pushback on hit)
|
||||
000A uint8 Range
|
||||
000B sint16 Attack speed (kickback; only applied if hitting something)
|
||||
|
||||
|
||||
#### Specific 4 Properties
|
||||
|
||||
This subclass describes energy beam weapons.
|
||||
|
||||
**Specific 4 Properties** (`BeamGunProp` struct) (13 bytes)
|
||||
|
||||
0000 [8]byte [Generic Weapon Info](../GenericWeaponInfo.md)
|
||||
0008 uint8 Max charge
|
||||
0009 uint8 Attack mass (impact force - pushback on hit)
|
||||
000A uint8 Range
|
||||
000B sint16 Attack speed (kickback)
|
||||
|
||||
|
||||
#### Specific 5 Properties
|
||||
|
||||
This subclass describes energy projectile weapons.
|
||||
|
||||
**Specific 5 Properties** (`BeamprojGunProp` struct) (18 bytes)
|
||||
|
||||
0000 [8]byte [Generic Weapon Info](../GenericWeaponInfo.md)
|
||||
0008 uint8 Max charge
|
||||
0009 byte Attack mass
|
||||
000A sint16 Attack speed (kickback)
|
||||
000C uint8 Projectile travel speed
|
||||
000D int32 Projectile triple (0x00CCSSTT)
|
||||
0011 byte Flags
|
||||
|
||||
|
||||
**Energy Projectile Weapon Flags** (1 byte)
|
||||
|
||||
0x02 Stun effect
|
||||
@@ -0,0 +1,9 @@
|
||||
### Level Gun Table (Class 0)
|
||||
|
||||
```L10``` is a table describing weapons and entries extend [the prefix](../../archives/levelObjects.md#class-specific-information) with their current ammo or charge.
|
||||
|
||||
**Level Gun Entry** (8 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 byte Ammo type / Charge
|
||||
0007 byte Ammo count / Temperature
|
||||
@@ -0,0 +1,12 @@
|
||||
### Ammo Properties
|
||||
|
||||
#### Generic Ammo Properties
|
||||
|
||||
**Generic Ammo Propertes** (`AmmoProp` struct) (14 bytes)
|
||||
|
||||
0000 [8]byte [Generic Weapon Info](../GenericWeaponInfo.md)
|
||||
0008 uint8 Cartridge size
|
||||
0009 uint8 Bullet mass (impact force - pushback on hit)
|
||||
000A sint16 Bullet speed (kickback)
|
||||
000C uint8 Range
|
||||
000D uint8 Recoil force
|
||||
@@ -0,0 +1,7 @@
|
||||
### Level Ammo Table (Class 1)
|
||||
|
||||
```L11``` is a table for ammo clips. Since clips are always full, entries have no further fields.
|
||||
|
||||
**Level Ammo Entry** (6 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
@@ -0,0 +1,42 @@
|
||||
### Physics Properties
|
||||
|
||||
#### Generic Properties
|
||||
|
||||
**Physics Generic Properties** (`PhysicsProp` struct) (1 byte)
|
||||
|
||||
0000 byte Physics flags
|
||||
|
||||
|
||||
**Physics Flags** (1 byte)
|
||||
|
||||
0x01 Emit light
|
||||
0x02 Bounce off walls
|
||||
0x04 Bounce off objects (real world), Pass through objects (cyberspace)
|
||||
0x08 Bounce off projectiles; set for all cyberspace projectiles
|
||||
|
||||
|
||||
> Cyberspace projectiles can't emit light, though they can bounce off walls.
|
||||
|
||||
|
||||
#### Specific 0 Properties
|
||||
|
||||
"Tracer" objects.
|
||||
|
||||
> These are not used in the engine.
|
||||
|
||||
**Physics Specific 0 Properties** (`TracerPhysicsProp` struct) (20 bytes)
|
||||
|
||||
0000 [4]int16 X coordinates
|
||||
0008 [4]int16 Y coordinates
|
||||
0010 [4]uint8 Z coordinates
|
||||
|
||||
|
||||
#### Specific 1 Properties
|
||||
|
||||
These properties are set for some `2/1/x` objects. More specifically: For cyberspace projectiles, also called "slow physics". The other projectiles of this subclass have their specific bytes zero.
|
||||
|
||||
**Physics Specific 1 Properties** (`SlowPhysicsProp` struct) (6 bytes)
|
||||
|
||||
0000 [6]byte Colour scheme
|
||||
|
||||
`Colour scheme` contains 6 palette indices from the game palette. The index into this list comes from the geometry properties, specifically from the [Set Colour and Shade](../../media/Geometry#set-colour-and-shade) command.
|
||||
@@ -0,0 +1,50 @@
|
||||
### Grenade Properties
|
||||
|
||||
#### Generic Grenade Properties
|
||||
|
||||
**Generic Grenade Propertes** (`GrenadeProp` struct) (15 bytes)
|
||||
|
||||
0000 [8]byte [Generic Weapon Info](../GenericWeaponInfo.md)
|
||||
0008 byte Touchiness
|
||||
0009 byte Blast radius
|
||||
000A byte Blast core range
|
||||
000B byte Blast damage
|
||||
000C uint8 Attack mass (impact force - pushback on hit)
|
||||
000D int16 Grenade Flags
|
||||
|
||||
`Touchiness` defines how likely a grenade is going to chain-explode if another was exploding nearby.
|
||||
> This value influences a calculation, based on a random value, as well as damage percentage. If the resulting number is higher than 7, then a chain-reaction is caused.
|
||||
> In the main game, this value is always `0x00`.
|
||||
|
||||
`Blast radius` specifies in tiles how far the explosion reaches, including visual effects (EMP scroll, explosion flash).
|
||||
|
||||
The main damage (from the `Generic Weapon Info`) is applied within the `Blast core range` of the explosion. This damage falls off from the center to the edge of the core range.
|
||||
|
||||
The `blast damage` is fully applied within the `blast core range`, additionally to the main damage. This damage falls off from the edge of the core range to the edge of the blast radius.
|
||||
|
||||
|
||||
**Grenade Flags** (2 bytes)
|
||||
|
||||
0x01 Explode on contact
|
||||
0x02 unused
|
||||
0x04 Explode by timer
|
||||
0x08 Explode by vicinity (mine)
|
||||
|
||||
> The behaviour of grenades is not exclusively governed by the flags field. Some seems to be hardcoded.
|
||||
> For instance, regular grenades marked with "timer" don't offer a time setting in the HUD and explode right after being thrown.
|
||||
> Regular timed grenades marked as "contact" ignore their timer setting, explode on object-contact, but not on floor/wall contact.
|
||||
|
||||
|
||||
#### Specific 1 Properties
|
||||
|
||||
Properties for timed grenades.
|
||||
|
||||
**Specific 1 Properties** (`TimedGrenadeProp` struct) (3 bytes)
|
||||
|
||||
0000 uint8 Minimum time
|
||||
0001 uint8 Maximum time
|
||||
0002 uint8 Timing deviation -- always 0x00
|
||||
|
||||
`Minimum time` and `maximum time` specify the range, in seconds, timed grenades can be set to.
|
||||
|
||||
> `Timing deviation` is always set to 0x00. Since it may also let the grenade go off earlier than expected, this may happen while still in the hand - which is presumably why it is unused in the main game.
|
||||
@@ -0,0 +1,44 @@
|
||||
## Level Explosive Table (Class 3)
|
||||
|
||||
```L13``` is a table describing explosives.
|
||||
|
||||
**Level Explosive Entry** (12 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [6]byte Explosive data
|
||||
|
||||
**Explosive Data** (6 bytes)
|
||||
|
||||
0000 int16 Unknown; Only set for live explosives
|
||||
0002 int16 State
|
||||
0004 int16 Timer time
|
||||
|
||||
|
||||
**State** (2 bytes)
|
||||
|
||||
0x0000 Inert
|
||||
0x0001 Thrown live grenade
|
||||
0x0005 Landed live grenade (land mines only, can't be picked up)
|
||||
|
||||
|
||||
The timer settings of explosives are stored in the [game state](../../archives/gameState.md).
|
||||
|
||||
The ```Timer time``` field is set to the same value as in the [level schedules](../../archives/levelSchedules.md), though modifying this value doesn't have an effect. The level timer is the authorative entry when to trigger the explosive.
|
||||
|
||||
|
||||
### Contact explosives 3/0/x
|
||||
|
||||
Contact explosives start a timer, though its expiry does nothing with the grenade.
|
||||
Land mines can be catched mid-air and re-thrown, others explode. Land mines enter state ```0x0005``` when touching the ground, after which they can't be picked up safely anymore.
|
||||
|
||||
> Although the game state also keeps time settings for these explosives, they can't be changed. Their timer don't have an effect anyway.
|
||||
|
||||
|
||||
### Timed explosives 3/1/0, 3/1/1
|
||||
|
||||
These explosives keep the state at ```0x0001```, even when landed. Live explosives can be picked up and re-thrown, until their timer sets them off.
|
||||
|
||||
|
||||
### Object explosion 3/1/2
|
||||
|
||||
This item has not been encountered.
|
||||
@@ -0,0 +1,9 @@
|
||||
### Level Drug Table (Class 4)
|
||||
|
||||
```L14``` is a table describing Drugs.
|
||||
|
||||
**Level Drug Entry** (6 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
|
||||
This entry does not contain any more information.
|
||||
@@ -0,0 +1,9 @@
|
||||
### Level Hardware Table (Class 5)
|
||||
|
||||
```L15``` is a table describing hardware.
|
||||
|
||||
**Level Hardware Entry** (7 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 byte Hardware version
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
## Level Software Table (Class 6)
|
||||
|
||||
```L16``` is a table describing software - programs, logs, data...
|
||||
|
||||
**Level Software Entry** (9 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [3]byte Software data
|
||||
|
||||
|
||||
### Cyberspace programs 6/0/x, 6/1/x, 6/2/x
|
||||
|
||||
**Cyberspace program data** (3 bytes)
|
||||
|
||||
0000 byte Version
|
||||
0001 [2]byte Unused
|
||||
|
||||
|
||||
> The three subclasses can be considered "aggressive programs", "defensive programs" and "boosts". Boosts ignore the version.
|
||||
> Although several programs are defined, only a few are used.
|
||||
> Different version numbers also change the color of the cube.
|
||||
|
||||
|
||||
### Fun pack modules 6/3/0
|
||||
|
||||
**Fun pack module data** (3 bytes)
|
||||
|
||||
0000 byte Game mask
|
||||
0001 [2]byte Unused
|
||||
|
||||
**Game mask** (1 byte)
|
||||
|
||||
0x01 Ping
|
||||
0x02 Eel Zapper
|
||||
0x04 Road
|
||||
0x08 Botbounce
|
||||
0x10 15
|
||||
0x20 TriopToe
|
||||
0x40 Gameb (Not working, gives "not installed" message)
|
||||
0x80 Wing 0
|
||||
|
||||
|
||||
### Multimedia data 6/4/0, 6/4/1
|
||||
|
||||
**Multimedia software data** (3 bytes)
|
||||
|
||||
0000 byte Unused
|
||||
0001 byte Index
|
||||
0002 byte Type
|
||||
|
||||
**Multimedia type** (1 byte)
|
||||
|
||||
0x00 E-Mail
|
||||
0x01 Log
|
||||
0x02 Data
|
||||
|
||||
> In the game, e-mails are received through triggers, logs are only in real-world levels, and data only in cyberspace levels. The engine supports placing any of them in any level type.
|
||||
|
||||
|
||||
#### Logs
|
||||
|
||||
For logs, the ```Log resource offset``` is based on the resource ID ```0x09B8```. The high nibble is used as the level identifier - into
|
||||
which category the log should be put.
|
||||
|
||||
See [Electronic Messages](../../content/ElectronicMessages.md) for details on messages.
|
||||
|
||||
> 6/4/0 are called "TEXT", behave like 6/4/1 "EMAIL", and are only used as logs.
|
||||
|
||||
|
||||
|
||||
## Cyberspace "Scenery" Software (Class 7, in cyberspace)
|
||||
|
||||
In cyberspace levels, ```L17``` is a table for additional software. It acts as an overflow for software if the first table is full.
|
||||
|
||||
**Scenery Software Entry** (16 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [10]byte Scenery software data
|
||||
|
||||
|
||||
### Scenery software 7/3/2 ("GLOW BULB"), 7/2/0 ("SIGN")
|
||||
|
||||
**Scenery software data** (10 bytes)
|
||||
|
||||
0000 int16 Parameter
|
||||
0002 int32 Subclass
|
||||
0006 int32 Type
|
||||
|
||||
|
||||
For entries that specify a program, ```Parameter``` specifies the version. For fun packs, it is the game mask.
|
||||
|
||||
> This type is only used for software with a single parameter; Found only for programs and fun packs.
|
||||
@@ -0,0 +1,220 @@
|
||||
## Level BigStuff Table (Class 7)
|
||||
|
||||
```L17``` is a table describing big items in real-world levels.
|
||||
|
||||
Cyberspace levels may re-use "big stuff" entries for further software entries. These entries need to be
|
||||
interpreted differently. See [Software](../06_Software/levelSoftwareEntry.md).
|
||||
|
||||
|
||||
**Level BigStuff Entry** (16 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [10]byte BigStuff Info
|
||||
|
||||
### Displays
|
||||
|
||||
There are several big items that are capable of displaying (animated) content. They reuse the following common types:
|
||||
|
||||
**Display Info** (10 bytes)
|
||||
|
||||
0000 int16 Frame count
|
||||
0002 int16 Loop type
|
||||
0004 int16 Alternation type
|
||||
0006 int16 Picture source
|
||||
0008 int16 Alternate picture source
|
||||
|
||||
Animated screens are also controlled by the [Loop Configuration](../../archives/loopConfiguration.md). If not, they use their own loop type.
|
||||
|
||||
**Loop Type** (1 byte)
|
||||
|
||||
0x00 Forward
|
||||
0x01 Forward/Backward
|
||||
0x02 Backward
|
||||
0x03 Forward/Backward
|
||||
|
||||
> Other values have been found as well, without effect; The engine defaults to forward looping.
|
||||
|
||||
|
||||
** Alternation Type** (1 byte)
|
||||
|
||||
0x00 Don't alternate
|
||||
0x03 Alternate randomly
|
||||
|
||||
> Not all alternate source combinations work properly. Commonly it is used to alternate to a text.
|
||||
|
||||
|
||||
**Picture Source** (2 bytes)
|
||||
|
||||
This field specifies what shall be shown. It has the following cases:
|
||||
|
||||
0x0000 .. 0x00F5 Image frames, offset from resource 0x0141
|
||||
0x00F6 Static fading into SHODAN's face
|
||||
0x00F7 Unknown (only found to display static)
|
||||
0x00F8 .. 0x00FF Surveillance screens 0 .. 7
|
||||
0x0100 .. 0x017E Text message from resource 0x0877
|
||||
0x017F Random number for CPU rooms, level 1-6 before destroying nodes.
|
||||
0x0180 .. 0x01FF Text message, scrolling vertically
|
||||
|
||||
For surveillance screens, the sources of screens 0-7 are specified in the [Surveillance Sources Table](../../archives/surveillanceCameras.md).
|
||||
|
||||
|
||||
The following big items support displays:
|
||||
7/0/6 (TV), 7/0/7 (COMPUTER MONITOR),
|
||||
7/2/6 (SCREEN, small), 7/2/8 (SCREEN, large), 7/2/9 (SCREEN, medium),
|
||||
with variation: 7/5/5 (CONTROL PANEL), 7/5/6 (CONTROL PEDESTAL) (see below)
|
||||
|
||||
### Electronics 7/0/x
|
||||
|
||||
> Apart from some displays, nothing special
|
||||
|
||||
|
||||
### Furniture 7/1/x
|
||||
|
||||
#### Cabinets 7/1/2
|
||||
|
||||
**Cabinet Data** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 [2]int16 Object index
|
||||
0006 [4]byte Unused
|
||||
|
||||
Cabinets can contain up to two objects.
|
||||
|
||||
|
||||
#### Texturable furniture 7/1/5, 7/1/7, 7/1/8 (chairs and couches)
|
||||
|
||||
**Texturable Furniture Data** (10 bytes)
|
||||
|
||||
0000 [6]byte Unused
|
||||
0006 int16 Texture index
|
||||
0008 [2]byte Unused
|
||||
|
||||
If ```Texture index``` is not zero, it specifies the alternate texture to use for the "main" faces of the furniture.
|
||||
|
||||
|
||||
### Surfaces 7/2/x
|
||||
|
||||
These are big objects that are flat and should be placed at another surface.
|
||||
|
||||
#### Words 7/2/3
|
||||
|
||||
**Words BigStuff Data** (10 bytes)
|
||||
|
||||
0000 int16 Text index (within resource 0x0868)
|
||||
0002 int16 Font and size (bits 0-3 are font, 4-7 are size)
|
||||
0004 int16 Colour (palette index, 0 defaults to red)
|
||||
0006 [4]byte Unused
|
||||
|
||||
|
||||
#### Texture Maps 7/2/7
|
||||
|
||||
**Texture map big stuff** (10 bytes)
|
||||
|
||||
0000 [6]byte Unused
|
||||
0006 int16 Texture index
|
||||
0008 [2]byte Unused
|
||||
|
||||
Texture maps allow to place one tile from the level texture list at any arbitrary position.
|
||||
|
||||
### Lighting 7/3/x
|
||||
|
||||
### Medical equipment 7/4/x
|
||||
|
||||
#### Control Pedestals (buttons only) 7/4/0
|
||||
|
||||
These can trigger an object if used.
|
||||
|
||||
**Button Control Pedestal Info** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 int16 Trigger object index
|
||||
0004 [6]byte Unused
|
||||
|
||||
|
||||
#### Surgery Machines 7/4/3
|
||||
|
||||
**Surgery Machine Info** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 byte Broken state; 0x00 = OK, 0xE7 = broken
|
||||
0003 [2]byte Unused
|
||||
0005 byte Broken message index; Broken default: 0x61
|
||||
0006 [4]byte Unused
|
||||
|
||||
With all bytes zero, the surgery machine works normally.
|
||||
|
||||
When the ```Broken state``` field is set to a certain value (the game has ```0xE7``` for the one on level 2, though some other work, too), then the machine wouldn't work. When not working, the message identified with ```Broken message index``` is displayed in the HUD. (```0x61``` = "This machine is broken").
|
||||
|
||||
|
||||
#### Textureable Furniture 7/4/5 (chairs)
|
||||
|
||||
These have the same layout as the general textureable furniture (see above).
|
||||
|
||||
|
||||
### Science and security equipment 7/5/x
|
||||
|
||||
#### Security Cameras 7/5/4
|
||||
|
||||
**Security Camera Info** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 byte Panning switch; 0x00: stationary, 0x01: panning
|
||||
0003 [7]byte Unused
|
||||
|
||||
|
||||
#### Control Pedestals (with display) 7/5/5, 7/5/6
|
||||
|
||||
Control pedestals are similar to displays regarding the source of the display.
|
||||
Instead of having different loop options, they trigger an object if used.
|
||||
|
||||
**Display Control Pedestal Info** (10 bytes)
|
||||
|
||||
0000 int16 Frame count
|
||||
0002 int16 Trigger object index
|
||||
0004 int16 Alternation type
|
||||
0006 int16 Picture source
|
||||
0008 int16 Alternate picture source
|
||||
|
||||
|
||||
### Garden big stuff 7/6/x
|
||||
|
||||
### Bridges 7/7/x
|
||||
|
||||
#### Solid Bridges 7/7/0, 7/7/1
|
||||
|
||||
**Solid Bridge Info** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 byte Size. Bits 0-3: X, bits 4-7: Y
|
||||
0003 byte Height. 0 is default, level height units otherwise.
|
||||
0004 byte Top/Bottom texture
|
||||
0005 byte Side texture
|
||||
0006 [4]byte Unused
|
||||
|
||||
The size fields are defined as 0: 3D model default, 4: tile width.
|
||||
The texture fields have bit 7 set to indicate texture from level texture list. If 0, the other 7 bits index
|
||||
into ```citmat.res```.
|
||||
|
||||
> If either textures are to be taken from the level list, the object description will be that of the textures.
|
||||
> If a texture is to be taken from citmat.res, the texture index must be > 0, otherwise it will still be the first
|
||||
> level texture, even if bit 7 is 0.
|
||||
|
||||
|
||||
#### Force Bridges 7/7/7, 7/7/8, 7/7/9
|
||||
|
||||
**Force Bridge Info** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 byte Size. Bits 0-3: X, bits 4-7: Y -- see above
|
||||
0003 byte Height. 0 is default, level height units otherwise.
|
||||
0004 [2]byte Unused
|
||||
0006 byte Colour
|
||||
0007 [3]byte Unused
|
||||
|
||||
Object 7/7/8 is a placeholder for force bridges that have not been activated yet. These objects are invisible and are made to force bridges with the use of trigger action 24.
|
||||
|
||||
Force bridges of type 7/7/9 differ from the typical ones (7/7/7) in having a default height of zero and no animation when switched from type 8. They furthermore need a size explicitly set.
|
||||
|
||||
The engine supports several different values for ```Colour```. Used values are ```0x00``` for red and ```0xFE``` for green.
|
||||
|
||||
> Not all 256 colour possibilities have been tested, many resulted in dark red tones or solid colours. Usable variants were found from ```0xF7``` and above.
|
||||
@@ -0,0 +1,186 @@
|
||||
## Level SmallStuff Table (Class 8)
|
||||
|
||||
```L18``` is a table describing general small stuff.
|
||||
|
||||
**Level SmallStuff Entry** (16 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [10]byte SmallStuff data
|
||||
|
||||
### Junk 8/0/x
|
||||
|
||||
#### Papers 8/0/2
|
||||
|
||||
**Paper** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 int16 Paper ID
|
||||
0004 [6]byte Unused
|
||||
|
||||
The ```Paper ID``` refers to a paper text entry and is the offset from resource ID ```0x003C```.
|
||||
The referred text entries have multiple blocks and the engine simply concatenates all these strings to one text.
|
||||
|
||||
|
||||
#### Briefcases 8/0/7
|
||||
|
||||
**Briefcase** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 [4]int16 Object index
|
||||
|
||||
|
||||
### Broken Stuff 8/1/x
|
||||
|
||||
Nothing special.
|
||||
|
||||
|
||||
### Dead Bodies 8/2/x
|
||||
|
||||
#### Corpses 8/2/0 - 8/2/7
|
||||
|
||||
**Corpse** (10 bytes)
|
||||
|
||||
0000 byte Treasure type
|
||||
0001 byte Unused
|
||||
0002 [4]int16 Object index
|
||||
|
||||
The four ```Object index``` values determine the corpse's loot. More random loot can be added to empty slots based on the ```Treasure type```.
|
||||
|
||||
|
||||
**Treasure Type Enumeration** (1 byte)
|
||||
|
||||
0xF5 No treasure
|
||||
0xF6 Humanoid
|
||||
0xF7 Drone
|
||||
0xF8 Assassin
|
||||
0xF9 Warrior cyborg
|
||||
0xFA Flier bot
|
||||
0xFB Security 1 bot
|
||||
0xFC Exec bot
|
||||
0xFD Cyborg enforcer
|
||||
0xFE Security 2 bot
|
||||
0xFF Elite cyborg
|
||||
0x00 Standard corpse
|
||||
0x01 Loot-oriented corpse
|
||||
0x02 Repairbot
|
||||
0x03 Serv-bot
|
||||
|
||||
|
||||
> The treasure type values for corpses are the same as for [critter properties](../14_Critter/critterProperties.md), except offset by 11.
|
||||
|
||||
#### Severed Heads 8/2/13, 8/2/14
|
||||
|
||||
**Severed Head** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 byte Image index
|
||||
0003 [7]byte Unused
|
||||
|
||||
If ```Image index``` is zero, the generic mutilated head is shown. Otherwise, it is the index for a picture of a person, using that of e-mails.
|
||||
|
||||
|
||||
### Consumables 8/3/x
|
||||
|
||||
Nothing special.
|
||||
|
||||
|
||||
### Access Cards 8/4/x
|
||||
|
||||
**Access Card** (10 bytes)
|
||||
|
||||
0000 int16 Unknown
|
||||
0002 sint32 Access mask
|
||||
0006 [4]byte Unused
|
||||
|
||||
All access cards work the same way: When consumed, they add the given ```Access mask``` to the current priviledges and give a message whether and which new access was gained.
|
||||
|
||||
**Access mask** (sint32)
|
||||
|
||||
0x00000001 "None" - This priviledge is none and will not be added. Should not be used.
|
||||
0x000000FE Various generic priviledges
|
||||
0x00FFFF00 Used for "group" priviledges; Typically used with 8/4/10 (Group access card)
|
||||
0x7F000000 Personal priviledges; 0x01: D'Arcy, 0x10: Diego
|
||||
|
||||
8/4/11 items (Personal access cards) have a special handling if personal priviledges are set; When identifying the object, the name of the person is appended to the title.
|
||||
|
||||
> 8/4/0 (Current access levels) works like any other access card, though it doesn't have a proper icon (only an 'X'). In the game it is used only on level 1 for a few cases, purpose unknown.
|
||||
|
||||
|
||||
### Cyberspace Items 8/5/x
|
||||
|
||||
#### Integrity Restorative 8/5/1
|
||||
|
||||
**Integrity Restorative** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 byte Restoration amount
|
||||
0003 [7]byte Unused
|
||||
|
||||
Per default (```Restoration amount``` = 0), the item restores about 3/4 of integrity.
|
||||
|
||||
#### Security Defense Mine 8/5/2
|
||||
|
||||
**Security Defense Mine** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 byte Damage amount
|
||||
0003 [7]byte Unused
|
||||
|
||||
Per default (```Damage amount``` = 0), the item removes little amount (about one chevron).
|
||||
|
||||
|
||||
#### Security ID Module 8/5/3
|
||||
|
||||
**Security ID Module** (10 bytes)
|
||||
|
||||
0000 int16 Unknown
|
||||
0002 sint32 Access mask
|
||||
0006 [4]byte Unused
|
||||
|
||||
Works like access cards - see above.
|
||||
|
||||
#### Cyber Info Nodes 8/5/6, 8/5/8
|
||||
|
||||
**Cyber Info Node** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 int16 Text index
|
||||
0004 [6]byte Unused
|
||||
|
||||
For 8/5/6 (information nodes), the text index is for text resource ```0x0878```.
|
||||
For 8/5/8 (data fragments), the text index is for text resource ```0x087A```.
|
||||
|
||||
|
||||
#### Cyberspace Barricades 8/5/9
|
||||
|
||||
**Cyberspace Barricade** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 byte Size. Bits 0-3: X, bits 4-7: Y
|
||||
0003 byte Height. 0 is default, level height units otherwise.
|
||||
0004 [2]byte Unused
|
||||
0006 byte Colour
|
||||
0007 [3]byte Unused
|
||||
|
||||
Layout and properties are the same as for force bridges (7/7/7).
|
||||
|
||||
|
||||
#### Cyberspace Decoys 8/5/10
|
||||
|
||||
**Cyberspace Decoy** (10 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 int16 Destroy object index
|
||||
0004 [6]byte Unused
|
||||
|
||||
Normally, these cannot be destroyed in cyberspace. However, if placed in a map and made vulnerable to damage, decoys can be made to destroy another object when destroyed.
|
||||
|
||||
|
||||
### Wear and Tear Stuff 8/6/x
|
||||
|
||||
Nothing special.
|
||||
|
||||
|
||||
### Quest Items 8/7/x
|
||||
|
||||
Nothing special.
|
||||
@@ -0,0 +1,11 @@
|
||||
### Small Stuff Properties
|
||||
|
||||
#### Specific 5 Properties
|
||||
|
||||
These items (```8/5/x```) are cyberspace items.
|
||||
|
||||
**Cyberspace Items Specific Properties** (`CyberSmallstuffProp` struct) (6 bytes)
|
||||
|
||||
0000 [6]byte Colour scheme
|
||||
|
||||
```Colour scheme``` contains 6 palette indices from the game palette. The index into this list comes from the geometry properties, specifically from the [Set Colour and Shade](../../media/Geometry#set-colour-and-shade) command.
|
||||
@@ -0,0 +1,266 @@
|
||||
## Level Fixture Table (Class 9)
|
||||
|
||||
```L19``` is a table describing fixtures and electrical stuff.
|
||||
|
||||
**Level Fixture Entry** (30 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0008 [24]byte Fixture Specific Info
|
||||
|
||||
|
||||
### Buttons 9/0/x
|
||||
|
||||
Buttons come in various shapes and forms. All of them are triggers for actions and the entry data that of [actions](../Actions.md).
|
||||
|
||||
**Button Fixture Specific Info** (24 bytes)
|
||||
|
||||
0000 [22]byte Action data
|
||||
0016 uint16 Access mask
|
||||
|
||||
|
||||
The conditions for buttons are based on [game variables](../Conditions.md#game-variable-conditions).
|
||||
|
||||
```Access mask``` is an additional condition for the button. If not zero, the lower five bits can specify one required access level the hacker must have. The remaining 7 bits don't work properly or resolve to the "None" level.
|
||||
|
||||
|
||||
### Receptacles 9/1/x, 9/4/x
|
||||
|
||||
Most receptacles work in conjunction with the quest items (8/7/x). With the exception of antenna relay panels, they contain regular actions as data.
|
||||
Unless noted otherwise below, the conditions for receptacles are based on object types, with an optional trap message if the wrong item is used.
|
||||
|
||||
**Receptacle Fixture Specific Info** (24 bytes)
|
||||
|
||||
0000 [22]byte Action data
|
||||
0016 [2]byte Unused
|
||||
|
||||
**Receptacle Fixture Condition** (4 bytes)
|
||||
|
||||
0000 byte Object type
|
||||
0001 byte Object subclass
|
||||
0002 byte Object class
|
||||
0003 byte Trap message (optional)
|
||||
|
||||
|
||||
#### Antenna Relay Panel 9/1/3
|
||||
|
||||
**Antenna Relay Panel Specific Info** (24 bytes)
|
||||
|
||||
0000 [6]byte Unused
|
||||
0006 int16 Trigger object index 1
|
||||
000A int16 Trigger object index 2
|
||||
000E int16 Destroy object index
|
||||
|
||||
The two ```trigger object index``` values work only with trigger objects, they can't trigger arbitrary objects.
|
||||
|
||||
> Behaviour of relays is hardcoded: After accepting the plastique, their type changes to 9/1/4 and a level timer is started. When the timer expires, the panel explodes, the type changes again to 9/1/5, the two objects are triggered and the object-to-destroy is removed.
|
||||
|
||||
|
||||
#### Retinal ID Scanner 9/1/6
|
||||
|
||||
When using a head item on the retinal scanner, the condition field is compared against the head's ```Current Frame``` value (for object 8/12/13), or ```Current Frame + 11``` (for object 8/12/14). Note that this is different from the ```Image index``` value which determines how the head appears in the MFD.
|
||||
|
||||
### Stations 9/2/x
|
||||
|
||||
The conditions for stations are based on [game variables](../Conditions.md#game-variable-conditions).
|
||||
|
||||
#### Cyberspace Terminals 9/2/0
|
||||
|
||||
**Cyberspace Terminal Specific Info** (24 bytes)
|
||||
|
||||
0000 byte State
|
||||
0001 byte Unused
|
||||
0002 [4]byte Condition
|
||||
0006 int32 Target X
|
||||
000A int32 Target Y
|
||||
000E int32 Target Z
|
||||
0012 int32 Target Level
|
||||
0016 [2]byte Unused
|
||||
|
||||
The orientation of the player in the target cyberspace level can not be specified. The orientation will be taken over from the real world.
|
||||
|
||||
**State** (1 byte enumeration)
|
||||
|
||||
0: Off
|
||||
1: Active (Normal state)
|
||||
2: Locked. Trying to activate it gives an electrical shock.
|
||||
|
||||
|
||||
#### Energy Charge Stations 9/2/1
|
||||
|
||||
**Energy Charge Station Specific Info** (24 bytes)
|
||||
|
||||
0000 [2]byte Unused
|
||||
0002 [4]byte Condition
|
||||
0006 int32 Power amount
|
||||
000A int32 Recharge time in seconds
|
||||
000E int32 Object index
|
||||
0012 int32 Recharged timestamp
|
||||
0016 [2]byte Unused
|
||||
|
||||
The object identified by ```Object index``` is triggered every time when energy is drawn from the station.
|
||||
|
||||
The ```Recharged timestamp``` will be set to the game time when the station is usable again. There is no dedicated timer running.
|
||||
|
||||
|
||||
### Input Panels 9/3/x
|
||||
|
||||
The conditions for input panels are based on [game variables](../Conditions.md#game-variable-conditions).
|
||||
|
||||
**Input Panel Info** (24 bytes)
|
||||
|
||||
0000 [2]byte Unknown
|
||||
0002 [4]byte Condition
|
||||
0006 [18]byte Input panel info
|
||||
|
||||
|
||||
#### Access Panels (Puzzles) 9/3/0 to 9/3/3, 9/3/9, 9/3/10
|
||||
|
||||
Puzzles are either "wire" or "block" puzzles. The type of the puzzle is determined by a bit within the info structure.
|
||||
|
||||
##### Wire Puzzles
|
||||
|
||||
**Wire Puzzle Input Panel Info** (18 bytes)
|
||||
|
||||
0000 int32 Target object index (object to toggle on success)
|
||||
0004 byte Puzzle layout
|
||||
0005 uint8 Target power level out of 0xFF
|
||||
0006 uint8 Wire properties mask
|
||||
0007 int8 Puzzle type - must be 0x00 for wire puzzle
|
||||
0008 uint32 Target state of wires
|
||||
000C uint32 Current state of wires
|
||||
0010 [2]byte Unused
|
||||
|
||||
**Puzzle Layout** (1 byte bitmask)
|
||||
|
||||
0x0F Wire count; 0 default to 4 wires
|
||||
0xF0 Connector count per size; 0 defaults to 6 connectors
|
||||
|
||||
**Wire properties mask** (1 byte bitmask)
|
||||
|
||||
0x0F Color wires; All pink if not set
|
||||
0xF0 Solved state
|
||||
|
||||
> For the properties mask, any of the respective four bits needs to be set to count for the whole nibble.
|
||||
> ```Solved state``` is always ```0xF0```, whereas ```Color wires``` is only set as ```0x01```.
|
||||
|
||||
Wire states are stored as three-bit pairs, ordered from LSB to MSB (right to left). The first pair describes the first
|
||||
wire and the lower triple specifies the left connector.
|
||||
|
||||
This allows for puzzles up to 5 wires and 8 connectors, although only up to 6 connectors are visible.
|
||||
|
||||
|
||||
##### Block Puzzles
|
||||
|
||||
**Block Puzzle Input Panel Info** (18 bytes)
|
||||
|
||||
0000 int32 Target object index (object to toggle on success)
|
||||
0004 int16 State store object index (refers to a null trigger)
|
||||
0006 byte Unused - 0x00
|
||||
0007 int8 Puzzle type - must be 0x10 for block puzzle
|
||||
0008 int32 Puzzle layout
|
||||
000C [6]byte Unused
|
||||
|
||||
**Puzzle Layout** (4 byte bitmask)
|
||||
|
||||
0x00000001 Puzzle solved flag ("Circuit Activated")
|
||||
0x0000000E Unknown
|
||||
0x00000070 Coordinate of source connector
|
||||
0x00000180 Source location
|
||||
0x00000E00 Unknown
|
||||
0x00007000 Coordinate of destination connector
|
||||
0x00018000 Destination location
|
||||
0x00700000 Width
|
||||
0x07000000 Height
|
||||
0x70000000 Side effect type
|
||||
|
||||
The location values are 0: top, 1: bottom, 2: left, 3: right
|
||||
|
||||
Side effects are:
|
||||
|
||||
0: Toggle all blocks horizontally/vertically from the changed one (across the board)
|
||||
1: Toggle all surrounding 8 blocks
|
||||
2: Toggle all blocks diagonally from the changed one (across the board)
|
||||
3: Toggle all blocks horizontally, vertically and diagonally across the board
|
||||
4: None
|
||||
|
||||
The state of the puzzle is stored in the referred ```State store object```, a trigger with no action.
|
||||
|
||||
The trigger info block is repurposed and at its offset ```0006``` there are 4 uint32 fields, concatenated to a 128 bit array.
|
||||
Starting with the LSB from this bit array, 3 bits are repeatedly taken to fill the blocks from left to right, top to bottom.
|
||||
This allows a maximum puzzle size of 42 blocks (6x7 or 7x6).
|
||||
|
||||
The blocks are:
|
||||
|
||||
0: Nothing (empty)
|
||||
1: Inactive (x)
|
||||
2: Active (+)
|
||||
3: Active (+) - not used
|
||||
4: Full node
|
||||
5: Full node - not used
|
||||
6: Hollow node
|
||||
7: Hollow node - not used
|
||||
|
||||
```Full nodes``` require only one incoming connection to forward power to the other three neighbours.
|
||||
```Hollow nodes``` require two incoming connections to forward power to the other two neighbours.
|
||||
|
||||
#### Elevator Panels 9/3/4, 9/3/5, 9/3/6
|
||||
|
||||
**Elevator Input Panel Info** (18 bytes)
|
||||
|
||||
0000 int16 Destination object index 2
|
||||
0002 int16 Destination object index 1
|
||||
0004 int16 Destination object index 4
|
||||
0006 int16 Destination object index 3
|
||||
0008 int16 Destination object index 6
|
||||
000A int16 Destination object index 5
|
||||
000C int16 Accessible bitmask (which floors are accessible)
|
||||
000E int16 Elevator shaft bitmask (which floors does the shaft connect)
|
||||
0010 [2]byte Unused
|
||||
|
||||
If a floor bit is set in the ```Elevator shaft bitmask``` field but not in the ```Accessible bitmask``` field, using
|
||||
that button gives the "Shaft damage" message. The MFD is capable of displaying up to 12 floors.
|
||||
|
||||
The ```Destination object index``` values refer to the object index of the elevator panels in the other levels. Note the swapped order of the index values. Presumably the six values are loaded as three int32 values first, and then the index values are extracted. The Nth bit from the accessible bitmask, counted from LSB, references the Nth destination object index.
|
||||
|
||||
For an elevator panel to work properly (and not crash the game), the following conditions must be met:
|
||||
* The panel must be in a tile which has the elevator music set. (Music index ```0xF``` in tile flags.)
|
||||
* The panels envolved in a level transition must reference each other. In other words, all panels of one connected elevator must have the same configuration.
|
||||
|
||||
> Referencing an object from another level requires an editor to keep track of inter-level references. Or burden the user.
|
||||
> The game uses only up to three active floors.
|
||||
|
||||
> The elevator panel on level 1 has the first byte of the input panel structure set to ```0x01```. Purpose and effect unknown.
|
||||
|
||||
|
||||
#### Number Pads 9/3/7, 9/3/8
|
||||
|
||||
**Number Pad Input Panel Info** (18 bytes)
|
||||
|
||||
0000 int16 3-digit combination 1
|
||||
0002 int16 Trigger object index 1
|
||||
0004 int16 3-digit combination 2
|
||||
0006 int16 Trigger object index 2
|
||||
0008 int16 3-digit combination 3
|
||||
000A int16 Trigger object index 3
|
||||
000C int16 Fail object index
|
||||
000E [4]byte Unknown
|
||||
|
||||
The 3-digit combinations are stored in [Binary-Coded-Decimal](https://en.wikipedia.org/wiki/Binary-coded_decimal) right-bound,
|
||||
so the combination ```451``` is stored as ```0x0451```.
|
||||
|
||||
A combination must be something else than "000" to be active ("000" is always wrong).
|
||||
Combinations must not be entered in sequence, any of the three combinations is valid at any time.
|
||||
|
||||
If the ```Fail object index``` refers to a valid object, this one is triggered when a wrong combination was entered.
|
||||
|
||||
> One number pad on level 0 has the first byte of the input panel structure set to ```0x06```. Purpose and effect unknown.
|
||||
|
||||
|
||||
### Cyberspace Switches 9/5/x
|
||||
|
||||
Cyberspace switches are triggers for actions and the entry data that of [actions](../Actions.md).
|
||||
|
||||
0000 [22]byte Action data
|
||||
0016 [2]byte Unused
|
||||
|
||||
The conditions for cyberspace switches are based on [game variables](../Conditions.md#game-variable-conditions).
|
||||
@@ -0,0 +1,29 @@
|
||||
## Level Door Table (Class 10)
|
||||
|
||||
```L20``` is a table describing doors and barriers.
|
||||
|
||||
**Level Door Entry** (14 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [8]bytes Door Data
|
||||
|
||||
|
||||
**Door Data** (8 bytes)
|
||||
|
||||
0000 int16 Lock variable index
|
||||
0002 byte Lock message
|
||||
0003 byte Force door colour index
|
||||
0004 byte Required access level
|
||||
0005 byte Auto-close time; in units of approximately 0.5 seconds - common default is 0x0C
|
||||
0006 int16 Second door object index
|
||||
|
||||
|
||||
The ```Lock variable index``` determines whether a door is locked. If the referenced boolean variable is 1, then the door won't open when used. If the door is triggered by other means, the door is unlocked and the index is reset to zero.
|
||||
Using the door while being locked, the message according to ```Lock message``` is shown. The message index is into the text resource ```0x0871```, with a block offset of ```7```. (```0x00``` gives the default "The door is locked" at index ```7```).
|
||||
|
||||
The ```Required access level``` indicates which [access level](../content/AccessLevels.md) the hacker needs to activate
|
||||
(open) the door. If zero, no special access is required. This values is ```0xFF``` for doors "locked by SHODAN level security".
|
||||
Such doors have a separate trigger referring these doors.
|
||||
|
||||
The ```Second door object index``` refers to a second door to trigger when activating this one.
|
||||
Bulkhead doors for instance reference each other this way.
|
||||
@@ -0,0 +1,27 @@
|
||||
### Animating Properties
|
||||
|
||||
#### Generic Animating Properties
|
||||
|
||||
**Generic Animating Propertes** (`AnimatingProp` struct) (2 bytes)
|
||||
|
||||
0000 byte Frame time
|
||||
0001 byte Flags
|
||||
|
||||
The `frame time` specifies the time of a single frame of the animation. A value of `0xFF` means a time of approximately 0.9 seconds. All animations have this value set to `0x1E` (30).
|
||||
|
||||
|
||||
**Animating Flags** (1 byte)
|
||||
|
||||
0x01 Emit light; The animation lights up the area with one tile radius for its duration.
|
||||
|
||||
|
||||
> Light is only emitted by objects placed by the engine. This flag is only set for such temporary animations, such as explosions (`11/2/x`), but works for impacts as well (`11/1/x`).
|
||||
|
||||
|
||||
#### Specific 2 Properties
|
||||
|
||||
"Explosion" animations.
|
||||
|
||||
**Specific 2 Properties** (1 byte)
|
||||
|
||||
0000 byte Frame explode
|
||||
@@ -0,0 +1,136 @@
|
||||
## Level Trap Table (Class 12)
|
||||
|
||||
```L22``` is a table describing trap items and general marker.
|
||||
|
||||
**Level Trap Entry** (28 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [22]byte Trap data
|
||||
|
||||
### Infrastructure 12/0/x
|
||||
|
||||
#### Critter AI Hints 12/0/7
|
||||
|
||||
**Critter AI Hint Data** (22 byte)
|
||||
|
||||
0000 [6]byte Unused; A few have the first byte 0x06
|
||||
0006 int16 Next object index
|
||||
0008 [10]byte Unused
|
||||
0012 int16 Trigger object flag -- 0: off, 1: on
|
||||
0014 int16 Trigger object index
|
||||
|
||||
AI hint marker are arranged to form a loop with their ```next object index``` fields. They describe a patrolling path for critters.
|
||||
If the ```trigger object flag``` is set to ```0x01```, the object identified by ```trigger object index``` will be triggered approximately 1.5 seconds after a critter entered the tile this marker is in.
|
||||
|
||||
> These patrolling paths appear to work only under special circumstances. They are rarely used in the main game and so far have been found to properly work only on level 9 for a mutated cyborg.
|
||||
> The main reason for these hints not properly working is that roaming critters only walk when the hacker is within their vicinity - which often already makes them hostile. The cyborg on level 9 initially is docile, thus not concerned about a (passive) hacker. Its 4 state bytes are ```00 00 04 00``` and requires the second loot object to point to the first hint.
|
||||
> Critters take these hints as such - they first walk into their direction, and continue to walk after passing them. Without a new hint, they will wander off in random directions. The cyborg on level 9 properly walks back and forth because its linear back-and-forth path has a hint for ever tile, and the two edges of the path are in coves, within which the cyborg bumps against the walls until properly turned around.
|
||||
|
||||
#### Repulsors 12/0/10
|
||||
|
||||
**Repulsor Data** (22 byte)
|
||||
|
||||
0000 [10]byte Unused; A few have the first byte 0x06 without effect
|
||||
000A int32 Start height
|
||||
000E int32 End height
|
||||
0012 int32 Repulsion flags; 0x00000001: disabled (float down); 0x00000008: strong repulsor
|
||||
|
||||
The ```start height``` and ```end height``` values have a unit of ```0x00010000``` for one tile height. An ```end height``` of zero means endless.
|
||||
Both values are measured from the floor. Repulsion only happens if the hacker is within these limits.
|
||||
|
||||
|
||||
#### Triggers 12/0/x (with exceptions)
|
||||
|
||||
The type of the trigger object determines its cause. The trap data is then that of [actions](../Actions.md).
|
||||
|
||||
Trigger Types:
|
||||
|
||||
0: Entry; Hacker enters tile (mid-air or per foot)
|
||||
1: Null; Must be set off externally. Also used as data storage.
|
||||
2: Floor; Hacker touches floor of this tile (per foot exclusively)
|
||||
3: Player Death; Used to resurrect Hacker
|
||||
4: Death Watch; When certain objects (or types of objects) are destroyed. Common for CPU nodes.
|
||||
5: Area Enter; Hacker enters (or leaves) a given radius
|
||||
6: Area Continuous; Hacker enters any tile inside (or outside) a given radius
|
||||
7: This is not a trigger! See AI hints above.
|
||||
8: Level Entry; Used for instance to initialize starting health
|
||||
9: Continuous; Unused
|
||||
10: This is not a trigger! See repulsors above.
|
||||
11: Ecology; Certain objects go extinct
|
||||
12: SHODAN; Triggered when level security changes
|
||||
|
||||
##### Conditions
|
||||
|
||||
Nearly all triggers have conditions based on [game variables](../Conditions.md#game-variable-conditions).
|
||||
|
||||
The following exceptions exist:
|
||||
* 4 (Death Watch Trigger): A union of [object type][obj-type-cond] and [object index conditions][obj-index-cond]
|
||||
* 5, 6 (Area Trigger): A radius around the trigger. See below.
|
||||
* 11 (Ecology Trigger): A combination of [object type][obj-type-cond] and a limit value. See below.
|
||||
|
||||
[obj-type-cond]: ./Conditions.md#object-type-conditions
|
||||
[obj-index-cond]: ./Conditions.md#object-index-conditions
|
||||
|
||||
##### Area Triggers
|
||||
|
||||
These triggers activate when the hacker enters or leaves a circular area around the trigger. The radius of this area is determined by the condition.
|
||||
|
||||
**Area Trigger Condition** (4 bytes)
|
||||
|
||||
0000 sint32 Radius (in tiles)
|
||||
|
||||
If the ```radius``` is between 1 and 4095, the trigger activates when the hacker is within a circular area of that size around the trigger's tile. A negative radius will activate the trigger when the hacker is outside of the circle instead (e.g. if the radius is -5, the trigger activates when the hacker is at least 5 tiles away from the trigger).
|
||||
|
||||
Trigger type 5 ("Area Enter") activates once the hacker either enters (positive radius) or leaves (negative radius) the area. Type 6 ("Area Continuous") activates when the hacker enters any tile that is either inside (positive radius) or outside (negative radius) of the area.
|
||||
|
||||
##### Ecology Triggers
|
||||
|
||||
These triggers watch a certain type of objects as their condition, together with a limit value. Whenever the current count of these objects is changed to a number below the limit value, the action is executed.
|
||||
|
||||
**Ecology Trigger Condition** (4 bytes)
|
||||
|
||||
0000 byte Type
|
||||
0001 byte Subclass
|
||||
0002 byte Class
|
||||
0003 byte Limit
|
||||
|
||||
Note: The action is executed more than once. How often the action is executed is dependent on the delta. If the new object count equals to (limit-1), then the action is executed twice. If the new object count is less than that, the action is executed three times.
|
||||
|
||||
> The layout for the C/S/T is the common one in an int32 value, with the high-byte representing the limit value.
|
||||
|
||||
> The game watches only critters, typically to spawn new ones. The trigger also works with other classes.
|
||||
|
||||
|
||||
### Trip Beams 12/1/x
|
||||
|
||||
These are not used in the game.
|
||||
|
||||
|
||||
### Map Marker 12/2/x
|
||||
|
||||
Only two types are used in the game.
|
||||
|
||||
|
||||
#### Map Notes 12/2/3
|
||||
|
||||
**Map Note Marker Data** (22 bytes)
|
||||
|
||||
0000 [18]byte Unused
|
||||
0012 int32 Entry offset
|
||||
|
||||
The ```Entry offset``` points into ```L46``` ([map notes](mapInformation.md#map-notes)) for the text entry. When a map note is removed and the whole table is defragmented, all the entry offsets are changed accordingly.
|
||||
|
||||
|
||||
#### Music Voodoo Marker 12/2/4
|
||||
|
||||
**Music Voodoo Marker Data** (22 byte)
|
||||
|
||||
0000 [6]byte Unused
|
||||
0006 byte Music flavour
|
||||
0007 [15]byte Unused
|
||||
|
||||
The ```Music flavour``` is an index, with a range of ```0x00```..```0x04```, referencing patches of "music" resembling industrial noise.
|
||||
They have a rectangular area of effect which covers 14x14 tiles, centered on the tile of the trap.
|
||||
The music is only played if the current tile has a music index of zero.
|
||||
|
||||
> This is used extensively on maintenance level, the 4 flight decks, as well as for the maintenance tunnels on the groves.
|
||||
@@ -0,0 +1,25 @@
|
||||
## Level Container Table (Class 13)
|
||||
|
||||
```L23``` is a table describing containers.
|
||||
|
||||
**Level Container Entry** (21 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [4]int16 Contained object indices
|
||||
|
||||
for crates (13/0/x):
|
||||
000E byte Width
|
||||
000F byte Depth
|
||||
0010 byte Height
|
||||
0011 byte Top/Bottom texture number
|
||||
0012 byte Side texture number
|
||||
|
||||
For the crate-specific values (dimensions and textures), if a value is 0, the default value from the 3D model is used.
|
||||
The textures are taken from the resources in ```citmat.res```, based on ```0x0884```.
|
||||
|
||||
> Texture numbers from ```0x80``` have been found to take the textures from the level texture list.
|
||||
> It is unclear if this is intentional or a side-effect of how data is arranged in the engine.
|
||||
|
||||
> Barrels (13/1/x) can not be inspected and may still contain items. Destroying a barrel drops its contents.
|
||||
> There is one radioactive waste barrel (13/1/0) on level 4 which "contains" a hornet clip, which is lying right next to it.
|
||||
> This is most likely the result of a mistake.
|
||||
@@ -0,0 +1,113 @@
|
||||
### Critter Properties
|
||||
|
||||
#### Generic Critter Properties
|
||||
|
||||
**Generic Critter Propertes** (`CritterProp` struct) (75 bytes)
|
||||
|
||||
0000 byte Intelligence; unused
|
||||
0001 [21]byte Primary attack info
|
||||
0016 [21]byte Secondary attack info
|
||||
002B uint8 Perception
|
||||
002C uint8 Defence
|
||||
002D sint8 Projectile source height offset
|
||||
002E int32 Flags
|
||||
0032 byte Mirrored views; unused
|
||||
0033 [8]uint8 Frame numbers; Amount for each posture
|
||||
003B uint8 Animation speed
|
||||
003C byte Attack sound index
|
||||
003D byte Near sound index
|
||||
003E byte Hurt sound index
|
||||
003F byte Death sound index
|
||||
0040 byte Notice sound index
|
||||
0041 int32 Corpse triple - 0x00CCSSTT; zero for "none"
|
||||
0045 byte View count; for multi-view postures
|
||||
0046 byte Secondary attack probability
|
||||
0047 byte Disrupt probability
|
||||
0048 byte Treasure type
|
||||
0049 byte Hit effect -- 0x00: meat, 0x01: plant, 0x02: robot, 0x03: cyborg, 0x04: generic
|
||||
004A byte Attack key frame
|
||||
|
||||
`Perception` is a probability whether an AI detects hacker when visible during an AI interval.
|
||||
|
||||
The `projectile source height offset` is a vertical offset specifying from where projectiles should be launched.
|
||||
> This is set to some positive values for the Elite Guard and Mutated Cyborg, so that their projectils appear from their heads.
|
||||
|
||||
The `animation speed` specifies the time of a single frame of an animation. A value of `0xFF` means a time of approximately 0.9 seconds.
|
||||
|
||||
For all `sound indices`, a value of `0xFF` indicates "no sound".
|
||||
> No enemy has a sound set for being hurt in the main game.
|
||||
|
||||
`View count` determines how many frames are available per viewing direction. Cyberspace entities, as well as unused critters, have this set to `0x01`, all others have `0x08`. Changing these values messes up rendering of the critter, and/or all subsequent critters. The sequence of the corresponding images will have to be adjusted accordingly.
|
||||
|
||||
The `secondary attack probability` determines how likely the critter will use its secondary attack when close to the hacker. `0xFF` means always, `0x00` will have the critter use the secondary attack only when farther away.
|
||||
|
||||
The `disrupt probability` determines how likely the critter will be interrupted when being hit. `0xFF` means always, `0x00` will have the critter execute its attacks and movement without interruptions.
|
||||
|
||||
`Treasure type` is an enumeration value (ranging from `0x00` to `0x0E`), pointing into a hardcoded pool of possible loot. See below for the possible constants. The concrete loot is randomized accordingly.
|
||||
|
||||
The `attack key frame` value is an index into the attack animation, when the corresponding attack should take effect.
|
||||
|
||||
|
||||
**Critter Attack Info** (`CritterAttack` struct) (21 bytes)
|
||||
|
||||
0000 uint8 Damage type
|
||||
0001 uint8 Special damage type
|
||||
0002 [2]byte Unused
|
||||
0004 int16 Damage modifier
|
||||
0006 uint8 Offence value
|
||||
0007 uint8 Penetration
|
||||
0008 uint8 Attack mass
|
||||
0009 int16 Attack velocity
|
||||
000B uint8 Accuracy
|
||||
000C uint8 Attack range
|
||||
000D int32 Reload time, with 0x100 being approximately 0.9 seconds
|
||||
0011 int32 Projectile triple -- 0x00CCSSTT; zero for "none"
|
||||
|
||||
The `damage type` seems to be compatible with the damage type of [generic weapon info](../GenericWeaponInfo.md). Yet all damage types that affect hacker are handled equally; The two damage types `0x04` and `0x08` have no effect at all.
|
||||
> The main game only uses damage types `0x01` and `0x02` (and some combinations). `0x04` is also set for Diego as well as SHODAN, though this has no further effect.
|
||||
|
||||
The `offence value` is compared to the defence value of the target object. See [common properties](../../fileFormat/PropertyFiles.md#common-table) for details.
|
||||
|
||||
An `accuracy` of `0x00` will still have the critter hit, though not that often and with less damage.
|
||||
|
||||
The critter will want to get within the `attack range` to perform its attack.
|
||||
|
||||
|
||||
**Critter Properties Flags** (4 bytes)
|
||||
|
||||
0x00000001 Flying
|
||||
|
||||
> There are further constants defined, though not in use by the engine.
|
||||
> The properties file has some critters with flag `0x00000004` set, which indicated "small" critters.
|
||||
|
||||
|
||||
**Treasure Type Enumeration** (1 byte)
|
||||
|
||||
0x00 No treasure
|
||||
0x01 Humanoid
|
||||
0x02 Drone
|
||||
0x03 Assassin
|
||||
0x04 Warrior cyborg
|
||||
0x05 Flier bot
|
||||
0x06 Security 1 bot
|
||||
0x07 Exec bot
|
||||
0x08 Cyborg enforcer
|
||||
0x09 Security 2 bot
|
||||
0x0A Elite cyborg
|
||||
0x0B Standard corpse
|
||||
0x0C Loot-oriented corpse
|
||||
0x0D Repairbot
|
||||
0x0E Serv-bot
|
||||
|
||||
|
||||
#### Specific 3 Properties
|
||||
|
||||
These critters (`14/3/x`) are for cyberspace.
|
||||
|
||||
**Cyberspace Critters Specific Properties** (`CyberCritterProp` struct) (6 bytes)
|
||||
|
||||
0000 [3]byte Colour scheme
|
||||
0000 [3]byte Alternative colour scheme
|
||||
|
||||
The `colour scheme`s contain 3 palette indices from the game palette. The 'alternative' colours are used for critters attacking or being hostile.
|
||||
The index into this list comes from the geometry properties, specifically from the [Set Colour and Shade](../../media/Geometry#set-colour-and-shade) command.
|
||||
@@ -0,0 +1,89 @@
|
||||
## Level Critter Table (Class 14)
|
||||
|
||||
```L24``` is a table describing critters.
|
||||
|
||||
**Level Critter Entry** (46 bytes)
|
||||
|
||||
0000 [6]byte Level object prefix
|
||||
0006 [40]byte Level critter data
|
||||
|
||||
|
||||
**Level Critter Data** (40 bytes)
|
||||
|
||||
0000 int32 Pending Z-rotation. Values up to 0x608000 seen.
|
||||
0004 int32 Fixed forward velocity. Rare values of 0x0D000 and 0x090000 seen.
|
||||
0008 [2]byte Unknown, Unused
|
||||
000A int16 Hastiness. Values of 0x0050 and 0x0030 seen.
|
||||
000C int16 State timeout
|
||||
000E int16 Unknown - set to 0x0002 for a few critters.
|
||||
0010 int16 Unknown - set to arbitrary values.
|
||||
0012 [2]byte Unused
|
||||
0014 byte Roaming critter state
|
||||
0015 byte Primary critter state
|
||||
0016 byte Secondary critter state
|
||||
0017 byte Tertiary critter state
|
||||
0018 [6]byte AI coordinates A
|
||||
001E byte Always 0xFF
|
||||
001F byte AI coordinates B
|
||||
0020 [2]int16 Loot object indices
|
||||
0024 [2]byte Unknown, Unused
|
||||
0026 [2]byte Unknown, set only for a few roaming critters.
|
||||
|
||||
|
||||
```Pending Z-rotation``` is a rotation value that the critter wants to perform next. Only when this value is zero, it continues with its regular state.
|
||||
|
||||
```Fixed forward veloctiy``` is used for a few critters to give them a fixed forward speed. This speed can be different than their normal speed, and even make them slower than regular.
|
||||
|
||||
```Hastiness``` makes a few critter appear as if they were under the effect of a speedup-stimulant. Their actions, including their animations, are quicker.
|
||||
|
||||
```State timeout``` is an indicator on how long the critter will stay in this state. Observed only in "cautious" state.
|
||||
This time is reduced as long as the hacker is in the vicinity. When the time reaches zero, the critter becomes hostile.
|
||||
The time value is typically quite low. A few high values like 0x0062 have been observed.
|
||||
|
||||
```AI coordinates A``` and ```B``` appear to be some sort of coordinates. Changing them has no visible effect, so they may be scratch values for the AI, determining where to go next. They are used only for roaming critters.
|
||||
|
||||
```Always 0xFF``` must always be set to ```0xFF```, otherwise the critter is immediately hostile, regardless of where it is on the map. All critters in the main game have it set to ```0xFF```.
|
||||
|
||||
### Critter states
|
||||
|
||||
The state a critter is in is goverend by four bytes, which have meanings on their own, as well as combined effects. For simple cases, only the ```Primary critter state``` is used. This value is also the one modified by the "Set critter state" action.
|
||||
|
||||
A roaming critter has the ```Roaming critter state``` value set, and also needs other states to be set. Working combinations found so far are:
|
||||
* ```03 01 01 00```
|
||||
* ```02 01 01 00``` (not found in archive.dat)
|
||||
A critter only roams on its own if the hacker is within a radius of about 6 tiles.
|
||||
|
||||
A patrolling critter follows a path laid out by ```Critter AI Hint``` marker (See [traps](../12_Trap/levelTrapEntry.md#critter-ai-hints-1207)). The first marker of such a path must be referenced in the second ```loot object index```.
|
||||
> The only working example of such a critter is initially docile, and has a state combination of ```00 00 04 00```.
|
||||
|
||||
The ```Primary critter state``` holds the state the critter is currently behaving in. This state is also reported by the targeting tool.
|
||||
|
||||
**Primary Critter State** (1 byte)
|
||||
|
||||
0x00 docile
|
||||
0x01 cautious
|
||||
0x02 hostile
|
||||
0x03 cautious (?)
|
||||
0x04 attacking
|
||||
0x05 sleeping
|
||||
0x06 tranquilized
|
||||
0x07 confused
|
||||
|
||||
> Various combinations of the state values can be found in the main game. While they have different effects, their pattern is not clear.
|
||||
|
||||
**Critter Mood Enumeration**
|
||||
|
||||
0 Friendly
|
||||
1 Neutral
|
||||
2 Hostile
|
||||
3 Isolation
|
||||
4 Attacking
|
||||
|
||||
**Critter Orders Enumeration**
|
||||
|
||||
0 Guard
|
||||
1 Roam
|
||||
2 Sleep
|
||||
3 Patrol between two points
|
||||
4 Highway - Follow path
|
||||
5 No move (guarding without moving)
|
||||
@@ -0,0 +1,786 @@
|
||||
## 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](../../archives/gameState.md).
|
||||
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](14_Critter/levelCritterEntry.md) 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.
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
## Conditions
|
||||
|
||||
Conditions are filters for [actions](Actions.md) and for some [fixtures](09_Fixture/levelFixtureEntry.md) that don't use actions.
|
||||
|
||||
Conditions can examine different aspects of the state of the game or (current) level.
|
||||
|
||||
|
||||
### Game Variable Conditions
|
||||
|
||||
These conditions check the value of a game variable (also called "quest value").
|
||||
|
||||
**Game Variable Condition** (4 bytes)
|
||||
|
||||
0000 uint16 Variable key
|
||||
0002 byte Value
|
||||
0003 byte Failure message
|
||||
|
||||
The ```Failure message``` is a message (or indication) the player shall receive if the condition was not met.
|
||||
```0x00``` means no indication, ```0xFF``` is used for security warnings (blocked by SHODAN security);
|
||||
All other values are interpreted as text/audio message index.
|
||||
|
||||
|
||||
**Variable key** (2 bytes)
|
||||
|
||||
0x03FF Variable index
|
||||
0x0C00 Unused
|
||||
0x1000 Variable type; 0: boolean variable, 1: int16 variable
|
||||
0xE000 Comparison
|
||||
|
||||
**Comparison**
|
||||
|
||||
0: Variable must be equal to value
|
||||
1: Variable must be less than value
|
||||
2: Variable must be less than, or equal to, value
|
||||
3: Variable must be greater than value
|
||||
4: Variable must be greater than, or equal to, value
|
||||
5: Variable must be not equal to value
|
||||
6: Value must be greater than a random value of range 0..254 (variable value is ignored)
|
||||
|
||||
|
||||
### Object Type Conditions
|
||||
|
||||
These conditions check for a specific object type.
|
||||
|
||||
**Object Type Condition** (4 bytes)
|
||||
|
||||
0000 int32 Class/Subclass/Type encoded as 0x00CCSSTT
|
||||
|
||||
Note that the most significant byte needs to be ```0x00```.
|
||||
|
||||
> These conditions are used for the quest items and for death watch trigger.
|
||||
|
||||
|
||||
### Object Index Conditions
|
||||
|
||||
These conditions are level-specific and only used for death watch trigger.
|
||||
|
||||
**Object Index Condition** (4 bytes)
|
||||
|
||||
0000 int16 Object index
|
||||
0002 byte Unused
|
||||
0003 byte Condition marker = 0x01
|
||||
|
||||
|
||||
As these conditions are used for the same type of triggers as the object type conditions, the ```condition marker``` identifies the class of condition.
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
### Generic Weapon Info
|
||||
|
||||
This structure is reused for various offensive items.
|
||||
|
||||
**Generic Weapon Info** (`COMBAT_DATA_FIELDS` macro) (8 bytes)
|
||||
|
||||
0000 sint16 Damage
|
||||
0002 byte Offence value
|
||||
0003 byte Damage type
|
||||
0004 byte Special damage type
|
||||
0005 [2]byte Unused
|
||||
0007 uint8 Armour penetration
|
||||
|
||||
The `offence value` is compared to the defence value of the target object. See [Common Object Properties](../fileFormat/PropertyFiles.md#common-table) for details.
|
||||
|
||||
If `Armour penetration` is equal or higher than the `Armour` value of the object being hit, the full `Damage` is applied. Otherwise, the difference is subtracted from `Damage`. If the resulting value reaches 0 or lower, "No Damage" is displayed.
|
||||
|
||||
`Special damage type` matches the `Special vulnerabilities` sub-fields from [Common Object Properties](../fileFormat/PropertyFiles.md#common-table);
|
||||
It is split up into `0x0F` primary damage (double damage) and `0xF0` super damage (quad damage).
|
||||
|
||||
> Similar to the vulnerabilities in the common object properties, the damage type is a single 32bit value from `0003` in the source.
|
||||
|
||||
|
||||
**Damage Type Bitfield** (1 byte)
|
||||
|
||||
0x01 Explosion (impact)
|
||||
0x02 Energy
|
||||
0x04 Magnetic (EMP)
|
||||
0x08 Radiation
|
||||
0x10 Gas
|
||||
0x20 Tranquilizer
|
||||
0x40 Needle
|
||||
0x80 Bio
|
||||
@@ -0,0 +1,99 @@
|
||||
## Level Objects
|
||||
|
||||
A level object is anything that is not part of the basic level layout (the tile map). The game knows about 476 different objects.
|
||||
|
||||
Objects are identified using three values. They are divided by class, subclass and type. In this documentation such an identifier will be written as ```c/s/t```. For example, the energy charge station is ```9/2/1```.
|
||||
|
||||
> In the original source, such an identifier is called a ```TRIPLE```.
|
||||
|
||||
Information about level objects exists in two places:
|
||||
* Static properties, describing an object in general
|
||||
* Instance data, describing the state of a specific object instance in the game
|
||||
|
||||
The static properties are stored in a separate file. See [Property Files](../fileFormat/PropertyFiles.md) for basic information.
|
||||
Instance data is stored as part of an archive. See [Level Objects](../archives/levelObjects.md) for basic information.
|
||||
|
||||
### Known Classes, Subclasses and Types
|
||||
|
||||
The following table lists the object classes together with the available types per subclass:
|
||||
|
||||
| Class | Name | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
|:-----:|------------------------------------|----|----|----|----|----|----|----|----|
|
||||
| 0 | Gun | 5 | 2 | 2 | 2 | 3 | 2 | - | - |
|
||||
| 1 | Ammo | 2 | 2 | 3 | 2 | 2 | 2 | 2 | - |
|
||||
| 2 | Physics | 6 | 16 | 2 | - | - | - | - | - |
|
||||
| 3 | Grenade | 5 | 3 | - | - | - | - | - | - |
|
||||
| 4 | Drug | 7 | - | - | - | - | - | - | - |
|
||||
| 5 | Hardware | 5 | 10 | - | - | - | - | - | - |
|
||||
| 6 | Software | 7 | 3 | 4 | 5 | 3 | - | - | - |
|
||||
| 7 | Big Stuff | 9 | 10 | 11 | 4 | 9 | 8 | 16 | 10 |
|
||||
| 8 | Small Stuff | 8 | 10 | 15 | 6 | 12 | 12 | 9 | 8 |
|
||||
| 9 | Fixtures | 9 | 7 | 3 | 11 | 2 | 3 | - | - |
|
||||
| 10 | Door | 10 | 9 | 7 | 5 | 10 | - | - | - |
|
||||
| 11 | Animating | 9 | 11 | 14 | - | - | - | - | - |
|
||||
| 12 | Trap | 13 | 1 | 5 | - | - | - | - | - |
|
||||
| 13 | Container | 3 | 3 | 4 | 8 | 13 | 7 | 8 | - |
|
||||
| 14 | Critter | 9 | 12 | 7 | 7 | 2 | - | - | - |
|
||||
|
||||
> This information is not stored within the resource files, it is hardcoded in the engine.
|
||||
|
||||
|
||||
### Static Properties
|
||||
|
||||
The following table lists the byte sizes of the generic and specific property structures per class.
|
||||
Many of these bytes are all zero in ```objprop.dat```; In these cases no detailed data definition will be linked.
|
||||
|
||||
| Class | Generic | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|
||||
|:-----:|---------------------------------------------|-----------|-----------|-----------|-----------|-----------|-----------|----|----|
|
||||
| 0 | [2](00_Gun/gunProperties.md) | 1 | 1 | [16][0/2] | [13][0/3] | [13][0/4] | [18][0/5] | - | - |
|
||||
| 1 | [14](01_Ammo/ammoProperties.md) | 1 | 1 | 1 | 1 | 1 | 1 | 1 | - |
|
||||
| 2 | [1](02_Physics/physicsProperties.md) | [20][2/0] | [6][2/1] | 1 | - | - | - | - | - |
|
||||
| 3 | [15](03_Grenade/grenadeProperties.md) | 1 | [3][3/1] | - | - | - | - | - | - |
|
||||
| 4 | 17 | 7 | - | - | - | - | - | - | - |
|
||||
| 5 | 2 | 1 | 2 | - | - | - | - | - | - |
|
||||
| 6 | 2 | 1 | 1 | 1 | 1 | 1 | - | - | - |
|
||||
| 7 | 4 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
|
||||
| 8 | 2 | 1 | 1 | 1 | 1 | 1 | [6][8/5] | 1 | 2 |
|
||||
| 9 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | - | - |
|
||||
| 10 | 1 | 1 | 1 | 1 | 1 | 1 | - | - | - |
|
||||
| 11 | [2](11_Animating/animatingProperties.md) | 1 | 1 | [1][11/2] | - | - | - | - | - |
|
||||
| 12 | 1 | 1 | 1 | 1 | - | - | - | - | - |
|
||||
| 13 | 3 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | - |
|
||||
| 14 | [75](14_Critter/critterProperties.md) | 1 | 2 | 2 | [6][14/3] | 1 | - | - | - |
|
||||
|
||||
|
||||
> There is also the case of objects with a specific entry length of 0. This is the case for object types that didn't make it into the game (vending machines).
|
||||
> Though, this is only a guess. Yet, the serialization code of the source-port (based on the mac-port) shows a hack by shifting the offset back by 2 bytes after serializing the doors. So, something must have been done in the original engine.
|
||||
|
||||
[0/2]: 00_Gun/gunProperties.md#specific-2-properties
|
||||
[0/3]: 00_Gun/gunProperties.md#specific-3-properties
|
||||
[0/4]: 00_Gun/gunProperties.md#specific-4-properties
|
||||
[0/5]: 00_Gun/gunProperties.md#specific-5-properties
|
||||
[2/0]: 02_Physics/physicsProperties.md#specific-0-properties
|
||||
[2/1]: 02_Physics/physicsProperties.md#specific-1-properties
|
||||
[3/1]: 03_Grenade/grenadeProperties.md#specific-1-properties
|
||||
[8/5]: 08_SmallStuff/smallStuffProperties.md#specific-5-properties
|
||||
[11/2]: 11_Animating/animatingProperties.md#specific-2-properties
|
||||
[14/3]: 14_Critter/critterProperties.md#specific-3-properties
|
||||
|
||||
|
||||
### Object Names
|
||||
|
||||
The names are localized and [stored as texts](../media/Texts.md). The short names are stored in resource ```0x086D```, the long
|
||||
names are in resource ```0x0024```.
|
||||
|
||||
|
||||
### Object Bitmaps
|
||||
|
||||
Every object has bitmaps associated with it. The bitmaps are all stored in resource ```0x0546``` in ```objart.res```, starting with block 1 for the first object. Each object has at least 3 bitmaps associated, with additional in-world bitmaps specified as per ```Extra``` field of the [Common Object Properties](../fileFormat/PropertyFiles.md#common-table).
|
||||
|
||||
As a result, to determine the proper block number for a given object, the total number of previous (extra) bitmaps needs to be known.
|
||||
|
||||
The first image is the standard image, the second (and additional) bitmaps are in-world bitmaps, and the last one is a micro-image.
|
||||
|
||||
> The micro-images are sometimes fully transparent. This has been found for marker objects for instance.
|
||||
> Maybe a (future) mapping unit would have been able to show objects, except those that weren't meant to be seen by the player.
|
||||
> For such transparent bitmaps, the first bitmap shows some abstract presentation. For example, the "continuous trigger" has the infinity symbol as first image.
|
||||
> On the contrary, using the first bitmap exclusively for editors might not be usable either as they sometimes have the same image for different types (software instance).
|
||||
|
||||
Objects of render type ```Fragment``` have one extra bitmap. The first one contains the colour information and the extra bitmap the depth information; It is a "gray-scale" bitmap with ```0xD0``` as the center.
|
||||
@@ -0,0 +1,97 @@
|
||||
## Bitmaps
|
||||
|
||||
Bitmaps are images using a palette of colours. System Shock uses bitmaps exclusively for its graphics and uses one byte
|
||||
as index per pixel - thus 256 colours possible. The resources store such bitmaps with content type ```0x02``` and they are always compound, even if only one bitmap is stored.
|
||||
|
||||
Bitmaps are stored with a header, the pixel data (sometimes compressed), and an optional private palette.
|
||||
|
||||
### Header
|
||||
|
||||
**Bitmap Header** (`FrameDesc` struct) (28 bytes)
|
||||
|
||||
0000 [4]byte Unused. Always zero. (used as pointer in the engine)
|
||||
0004 byte Type -- 0x02: Uncompressed; 0x04 Compressed
|
||||
0005 byte Align -- Unused
|
||||
0006 uint16 Flags
|
||||
0008 sint16 Width
|
||||
000A sint16 Height
|
||||
000C uint16 Stride
|
||||
000E byte WidthFactor
|
||||
000F byte HeightFactor
|
||||
0010 [4]int16 HotspotBox: Left, Top, Right, Bottom
|
||||
0018 sint32 Private palette offset
|
||||
|
||||
The ```Flags``` is set to value ```0x0001``` then palette index ```0x00``` should be treated as a transparent pixel instead of painting it black.
|
||||
> Compressed images appear to default to transparency if the resolution of the game is 320x200. Higher resolutions require the flag set to behave identical.
|
||||
>
|
||||
> Other factors may also govern whether the bitmap should be treated with transparency - videos and level textures have their special handling in this regard.
|
||||
|
||||
The ```WidthFactor``` and ```HeightFactor``` specify the index of the highest set bit of ```Width``` and ```Height```
|
||||
respectively. For example, if Width is 320 (0x140), then the WidthFactor is 8 (1<<8 == 0x100).
|
||||
|
||||
`HotspotBox` is a placeholder for different applications. It can define a rectangle, or it only defines a point (using the first two values) for anchoring.
|
||||
|
||||
> For the existing images in the original resource files, all images have a ```Stride``` equal to ```Width```.
|
||||
|
||||
### Pixel Data
|
||||
|
||||
After the header, the pixel data is serialized. If the image is uncompressed (Type ```0x02```),
|
||||
```Height``` x ```Stride``` bytes make up the image. Compressed images (Type ```0x04```) use a simple run-length-encoding (RLE).
|
||||
|
||||
#### Pixel Compression
|
||||
|
||||
The compressed byte-stream contains the following byte sequences:
|
||||
|
||||
00 nn zz write nn bytes of value zz
|
||||
nn .. 0 < nn < 0x80: copy the following nn bytes
|
||||
80 lo hi lo hi are a little-endian uint16 nnnn, to be handled as follows:
|
||||
80 00 00 End of compressed data (Skip to end)
|
||||
80 lo hi 0 < hi < 0x80: skip (nnnn & 0x7FFF) output pixel
|
||||
80 lo hi .. 0x80 <= hi < 0xC0: copy the following (nnnn & 0x3FFF) bytes
|
||||
80 lo C0 hi == 0xC0: undefined (not encountered)
|
||||
80 lo hi zz 0xC0 < hi: write (nnnn & 0x3FFF) bytes of value zz
|
||||
nn 0x80 < nn: skip (nn & 0x7F) output pixel
|
||||
|
||||
Three cases exist to compress pixel data: skip a list of pixel, compress a list of a constant
|
||||
value and copy an arbitrary array of bytes. For each of the three, two encoding variants are used: a short and a long form.
|
||||
If a count is to be serialized that is higher than the long-form can store, the encoder uses the long-form to reduce this number to finalize with the short-form.
|
||||
|
||||
> Skipping output pixel is relevant for compressing video clips. Skipped pixel will retain the colour value from the previous frame.
|
||||
> For still images, initialize the output buffer with 0x00.
|
||||
>
|
||||
> To implement a compressor that creates output closest to the original content, use the following sequence. The term "reference" means either a previous frame bitmap, or a fictual frame with all bytes 0x00.
|
||||
> * From an array of bytes with length X, calculate the count Z of bytes at the end that are identical to reference. Compress only N bytes, where N = X - (Z % 0x7FFF).
|
||||
> The final sequence ```80 00 00``` implies to skip to the end. The encoder
|
||||
> seems to have had a limit of counting only up to 0x7FFF, so there may be further (long) skip entries before.
|
||||
> * Iterate through the pixel data from start to N:
|
||||
> * Count the extent of static value bytes
|
||||
> * Count the number of bytes identical to reference
|
||||
> * Determine encoding method
|
||||
> * If the pixel value shall be retained from the reference, skip the count of bytes
|
||||
> * Otherwise, if the count is more than three, encode the count and the constant value
|
||||
> * Otherwise, count the extent of an arbitrary array; Abort when more than three static or identical values are found in sequence; Encode this array.
|
||||
> * Skip the input bytes that have been serialized and continue with the loop
|
||||
> * Encode end of compressed data sequence.
|
||||
|
||||
|
||||
### Private Palette
|
||||
|
||||
The format also allows for an optional palette, which is specific for the bitmap. If an image has no private palette, then this
|
||||
entry is not present and the resource data ends directly after the pixel data.
|
||||
Without a private palette, the colours of the bitmap are context specific. See [Palettes](Palettes.md) for more information.
|
||||
|
||||
Private palettes are used for the splash screens at the beginning of the game, where nothing else is shown.
|
||||
The ```Private palette offset``` in the bitmap header specifies the absolute offset *from the beginning* of the resource to the private palette entry. This means in case of a compound resource, this offset measures across the previous resource blocks as well.
|
||||
|
||||
**Private Palette** (772 bytes)
|
||||
|
||||
0000 [4]byte Unknown. Always 0x00, 0x00, 0x00, 0x01
|
||||
0004 [256*3]byte RGB values
|
||||
|
||||
> The only working examples for this can be found in ```splash.res```.
|
||||
>
|
||||
> The resource file ```gamescr.res``` also contains three bitmaps with a private palette, but these palettes are not used and are ignored by the engine.
|
||||
> The three bitmaps in question are the help overlay (```ALT+o```), and are shown with the game world in the background. Since in these
|
||||
> cases the world can't change its colour, the screen can't use a private palette. By extension, the side-effects of the "Berserk" patch
|
||||
> also affect the colours of the help overlay.
|
||||
> Furthermore, for these three bitmaps, the values of offset fields are wrong as well.
|
||||
@@ -0,0 +1,33 @@
|
||||
## Fonts
|
||||
|
||||
This chapter documents the data format of the fonts. The game uses [bitmap fonts](https://en.wikipedia.org/wiki/Computer_font#Bitmap_fonts) which describe the characters.
|
||||
|
||||
The fonts are stored in single blocks within resources of type ```0x03```. They can be found in the file ```gamescr.res```.
|
||||
|
||||
All glyphs in the bitmap are lined up in a single line. There are no Y offsets per glyph, and the height is always equal to the height of the bitmap. An array of ```X-Offsets``` points to the start of a glyph and the width is equal the difference to the next offset.
|
||||
|
||||
### Binary Format
|
||||
|
||||
**Font Header** (84 bytes)
|
||||
|
||||
0000 uint16 Font Type -- 0x0000: Monochrome, 0xCCCC: Color
|
||||
0002 [34]byte Unknown -- always 0x00
|
||||
0024 int16 First character index (inclusive)
|
||||
0026 int16 Last character index (inclusive)
|
||||
0028 [32]byte Unknown -- always 0x00
|
||||
0048 int32 Offset to X-Offsets, from beginning of data
|
||||
004C int32 Offset to bitmap, from beginning of data
|
||||
0050 int16 Width of bitmap in bytes
|
||||
0052 int16 Height of bitmap in bytes
|
||||
|
||||
**X-Offsets** (2*N bytes)
|
||||
|
||||
The X-Offsets is an array of ```int16``` values. The length of the array is equal to the number of characters the font covers, plus one. The width of one glyph is always equal the difference to the next offset, even for the last one.
|
||||
|
||||
For a monochrome font, the offset is counted in bits, always beginning with the MSB.
|
||||
|
||||
**Bitmap** (W*H bytes)
|
||||
|
||||
Monochrome fonts have the glyphs packed as bits within the bytes, color fonts use the bytes as palette indices.
|
||||
|
||||
> Fonts that have an outline, primarily seen with the HUD fonts, don't store the outline information in the font bitmaps. The outlines are rendered at runtime.
|
||||
@@ -0,0 +1,182 @@
|
||||
## 3D Object Geometry
|
||||
|
||||
This chapter documents the data format of the three dimensional objects encountered in the game (tables, ICE in cyberspace, crates...).
|
||||
|
||||
All the geometry is stored in the file ```obj3d.res``` with content type ```0x0F```. Each resource in this file is compound with one data block. There is one object per resource (and data block).
|
||||
|
||||
Each three dimensional ```model``` consists of a list vertex definitions and a structure of ```nodes```, with the model itself being the root node. A node contains a list of ```anchors```, with each one having a normal vector and a reference point.
|
||||
Up to exactly one anchor per node may branch out to two further nodes (creating a binary tree). Further anchors contain lists of rendered ```faces```. Faces are either texture mapped or filled with a single colour.
|
||||
|
||||
### Binary Format
|
||||
|
||||
The data starts with 8 bytes of header information, followed by a list of "commands" which describe the structure.
|
||||
|
||||
**Geometry Header** (8 bytes)
|
||||
|
||||
0000 int16 Unknown -- always 0x0027
|
||||
0002 int16 Unknown -- always 0x0008
|
||||
0004 int16 Unknown -- always 0x0002
|
||||
0006 int16 Total number of Faces
|
||||
|
||||
> The ```Total number of Faces``` value does not seem to be authorative. There are a few entries in the resouce file which state a higher count than actually in the model.
|
||||
|
||||
**Model Command** (2+N bytes)
|
||||
|
||||
0000 int16 Model Command Identifier
|
||||
0002 N Command specific content
|
||||
|
||||
> There is no framing structure which would allow skipping command entries, so an implementation has to know of all commands beforehand.
|
||||
|
||||
|
||||
**fixed32/16** (4 bytes)
|
||||
|
||||
In the following, coordinates (and their offsets) are serialized as fixed floating point values in a 32/16 format.
|
||||
|
||||
0000 sint16 Integer value
|
||||
0002 uint16 Fraction (in 1/65536 units)
|
||||
|
||||
> For a simple implementation, it is sufficient to read the value as a ```sint32```, convert it to floating point and divide by 65536.0 .
|
||||
|
||||
|
||||
**Vector** (12 bytes)
|
||||
|
||||
A vector is serialized with three coordinates:
|
||||
|
||||
0000 fixed32/16 X
|
||||
0004 fixed32/16 Y
|
||||
0008 fixed32/16 Z
|
||||
|
||||
|
||||
### Geometry Commands
|
||||
|
||||
#### Vertex Definitions
|
||||
Vertices are always (and only) defined at the beginning of the model (the root node). Three ways exist: define a single vertex, multiple vertices or references to previous ones with offsets.
|
||||
|
||||
##### Define Single Vertex
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0015
|
||||
0002 int16 Unknown -- always 0x0000
|
||||
0004 Vector Vertex coordinates
|
||||
|
||||
##### Define Multiple Vertices
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0003
|
||||
0002 int16 Number of vertices
|
||||
0004 int16 Unknown -- always 0x0000
|
||||
0006 [N]Vector Coordinates of vertices
|
||||
|
||||
##### Define Vertex (One Offset)
|
||||
|
||||
0000 int16 Model Command Identifier -- X: 0x000A, Y: 0x000B, Z: 0x000C
|
||||
0002 int16 New vertex index
|
||||
0004 int16 Reference vertex index
|
||||
0006 fixed32/16 Offset value to coordinate as per command identifier
|
||||
|
||||
> In the existing files, the ```New vertex index``` has always been found to equal the current amount of known vertices, appending at the end of the list.
|
||||
|
||||
##### Define Vertex (Two Offsets)
|
||||
|
||||
0000 int16 Model Command Identifier -- XY: 0x000D, XZ: 0x000E, YZ: 0x000F
|
||||
0002 int16 New vertex index
|
||||
0004 int16 Reference vertex index
|
||||
0006 fixed32/16 Offset value to first coordinate as per command identifier
|
||||
0010 fixed32/16 Offset value to second coordinate as per command identifier
|
||||
|
||||
> In the existing files, the ```New vertex index``` has always been found to equal the current amount of known vertices, appending at the end of the list.
|
||||
|
||||
> To generate a list of vertex definitions as close as possible to the original files, follow these steps:
|
||||
> * Determine count of dissimilar vertices:
|
||||
> * From the list of vertices, iterate reverse from the tail.
|
||||
> * For each vertex, search the list below the current index if there is another vertex which has at least one identical coordinate.
|
||||
> * Abort this loop if the current vertex has no similar other. Vertices from beginning to the current index are all dissimilar.
|
||||
> * Depending on the count of dissimilar vertices, define them with either the single definition or the multiple definition.
|
||||
> * Now iterate forward through the list (until end), beginning with the first vertex after the dissimilar ones.
|
||||
> * For each vertex, again find another most similar from those coming before it (including those already handled in this loop).
|
||||
> * Compare the coordinates again.
|
||||
> * If two are identical, write a single offset definition (for the one coordinate not equal).
|
||||
> * If one is identical, write a double offset definition (for the two coordinates not equal).
|
||||
>
|
||||
> This list assumes the vertices are all unique and they were sorted to have the dissimilar ones come first. This must be done in
|
||||
> combination with modifying the face definitions as they refer to the vertices via indices.
|
||||
> Following this sequence will create a vertex definition with equal byte length as in the original. The differences to the original files are in which
|
||||
> reference vertices were taken.
|
||||
|
||||
#### Node Control
|
||||
|
||||
##### End Of Node
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0000
|
||||
|
||||
Every node is finished with this command.
|
||||
|
||||
##### Define Node Anchor
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0006
|
||||
0002 Vector Normal vector
|
||||
000E Vector Reference point
|
||||
001A int16 Byte offset to 'left' branch
|
||||
001C int16 Byte offset to 'right' branch
|
||||
|
||||
The offset values are based on the start of the command. Branch data comes only after the current node has ben finished; There is always only one ```End Of Node``` command pending. Branches are serialized depth-first.
|
||||
|
||||
> In the existing files always the 'right' branch has been found to be serialized first. Although only a few cases, several layers can be found within one branch. If a branch is not needed, it contains only the ```End Of Node``` command.
|
||||
|
||||
|
||||
#### Face Control
|
||||
|
||||
##### Define Face Anchor
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0001
|
||||
0002 int16 Anchor byte length (measured from start of this command)
|
||||
0004 Vector Normal vector
|
||||
0010 Vector Reference point
|
||||
001C N Face drawing commands
|
||||
|
||||
Faces within one ```Define Face Anchor``` command are either painted in a single colour (with an optional shade) or texture mapped.
|
||||
|
||||
##### Coloured Face
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0004
|
||||
0002 int16 Vertex count
|
||||
0004 [N]int16 Vertex indices
|
||||
|
||||
This command always has either a ```Set Colour``` or a ```Set Colour And Shade``` command before. It may be that several ```Coloured Face``` commands refer to the same setting.
|
||||
|
||||
##### Set Colour
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0005
|
||||
0002 int16 Colour palette index
|
||||
|
||||
##### Set Colour And Shade
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x001C
|
||||
0002 int16 Colour palette cross index
|
||||
0004 int16 Shade value (0..3)
|
||||
|
||||
The ```Colour palette cross index``` refers to a small lookup table from the corresponding static object properties. This lookup table is a list of always 6 palette indices.
|
||||
|
||||
> The data files contain cross indices of 0..6 . TSSHP skips those with value 0 and subtracts 1 from the remaining 6 values.
|
||||
|
||||
##### Texture Mapping
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0025
|
||||
0002 int16 Number of entries
|
||||
0004 [N]Entry Mapping entries
|
||||
|
||||
**Mapping Entry (10 bytes)**
|
||||
|
||||
0000 int16 Vertex index
|
||||
0002 fixed32/16 texture u coordinate
|
||||
0006 fixed32/16 texture v coordinate
|
||||
|
||||
##### Textured Face
|
||||
|
||||
0000 int16 Model Command Identifier -- 0x0026
|
||||
0002 int16 Texture identifier
|
||||
0004 int16 Vertex count
|
||||
0006 [N]int16 Vertex indices
|
||||
|
||||
This command always has a ```Texture Mapping``` command before.
|
||||
|
||||
The ```Texture identifier``` references a texture with a resource identifier base of ```0x01DB```, found in ```citmat.res```.
|
||||
The value of 0 specifies special, object specific handling.
|
||||
@@ -0,0 +1,40 @@
|
||||
## Palettes
|
||||
|
||||
The engine uses a graphic mode with 256 colors per pixel. The graphic resources (images and videos) use bitmaps together
|
||||
with palette information to resolve a pixel value (1 byte) to the corresponding RGB value (3x1 byte).
|
||||
|
||||
Depending on the game-state, different palettes are in use. The splash screens at the beginning are created using a
|
||||
```Private Palette``` (see the [bitmap](Bitmaps.md) format). Cutscenes have their own palette(s) and during the game,
|
||||
one specific palette is used throughout. This game palette is stored in ```gamepal.res```.
|
||||
|
||||
### Format
|
||||
|
||||
Palettes always have a size of 768 bytes, for 256 colors with 1 byte for each of the three colour channels.
|
||||
|
||||
**Palette** (768 bytes)
|
||||
|
||||
0000 [256*3]byte RGB values
|
||||
|
||||
### Transparency
|
||||
|
||||
Palette index 0 is used as a marker for fully transparent pixel. For instance, various decoration or critter sprites need
|
||||
to have transparent areas in order to lose the rectangular shape.
|
||||
|
||||
### Pixel Animation / Palette Looping
|
||||
|
||||
During the game various textures can be observed with small animations. Most typically seen with LED-like blinking effects.
|
||||
Instead of implementing this with multiple frames, the engine simply loops through the colors within a few groups.
|
||||
|
||||
The following groups (palette index values) are looped:
|
||||
|
||||
0x03 - 0x07: Changed every ~1200 msec
|
||||
0x0B - 0x0F: Changed every ~700 msec
|
||||
0x10 - 0x14: Changed every ~360 msec
|
||||
0x15 - 0x17: Changed every ~1800 msec
|
||||
0x18 - 0x1A: Changed every ~1430 msec
|
||||
0x1B - 0x1F: Changed every ~1080 msec
|
||||
|
||||
> These groups are looped even while the game is paused.
|
||||
>
|
||||
> Above switching times have been determined by counting frames of a video recording from dosbox, running within a VM.
|
||||
> Exact values may be different.
|
||||
@@ -0,0 +1,45 @@
|
||||
## Sound Effects
|
||||
|
||||
Sound effects are stored in ```digifx.res```, which contains resources of data type ```0x07```.
|
||||
The resources have IDs in the range from ```0x00C9``` to ```0x013B```, are uncompressed and have one effect per resource.
|
||||
|
||||
Each resource contains one sound effect, which is stored in the
|
||||
[Creative Voice File](http://wiki.multimedia.cx/index.php?title=Creative_Voice) format.
|
||||
|
||||
Although the format would allow for different sample formats, only unsigned 8-bit PCM audio (MIME type ```audio/L8```)
|
||||
is supported and expected. The sound effects don't use any special block types of the file format,
|
||||
only one ```Sound data``` block is present, followed by a ```Terminator``` block identifier. All effects have one channel (mono).
|
||||
|
||||
### Format
|
||||
The following is an extract of the above linked page, specialized to the use by the engine.
|
||||
|
||||
***Sound Effect***
|
||||
|
||||
0000 [19]byte Identifier text "Creative Voice File"
|
||||
0013 byte Identifier terminator: 0x1A
|
||||
0014 int16 Length of header (commonly 0x1A)
|
||||
0016 uint16 Version number (0x010A)
|
||||
0018 uint16 Version number validation
|
||||
|
||||
001A byte Sound data block type: 0x01
|
||||
001B [3]byte Length of block data (sample count + 2)
|
||||
|
||||
001E byte Frequency divisor
|
||||
001F byte Codec ID (audio/L8: 0x00)
|
||||
0020 []byte Samples
|
||||
|
||||
NNNN byte Terminator block type: 0x00
|
||||
|
||||
***Version Number***
|
||||
|
||||
The version number is encoded as a major and minor number, in the high and low bytes respectively.
|
||||
|
||||
The validation value is the result of building the binary complement of the version number and adding the constant ```0x1234```.
|
||||
|
||||
***Frequency Divisor***
|
||||
|
||||
The frequency divisor is used to calculate the sample rate with the following formula:
|
||||
|
||||
```
|
||||
sampleRate := 1000000 / (256 - frequencyDivisor)
|
||||
```
|
||||
@@ -0,0 +1,67 @@
|
||||
## Texts
|
||||
|
||||
All texts are stored in the language specific files ```cybstrng.res```, ```frnstrng.res``` and ```gerstrng.res```.
|
||||
These files contain 188 resources of type ```0x01```. They are compound with several blocks. Each block contains
|
||||
one string, which is always 0x00 terminated.
|
||||
|
||||
While the English strings may be readable according to standard ASCII, with the French and German options, texts
|
||||
need to be interpreted according to the DOS [code page 437](http://en.wikipedia.org/wiki/Code_page_437).
|
||||
|
||||
> Since texts are always presented through the game fonts, any one-byte codepage can be used - As long as the
|
||||
> corresponding font bitmaps match for the requested characters (bytes).
|
||||
|
||||
### Control Characters
|
||||
|
||||
For texts with multiple lines, ```0x0A``` acts as a newline marker.
|
||||
|
||||
```0x02``` is a soft-hyphen between syllables. Not all texts contain this character.
|
||||
|
||||
### Resource Overview
|
||||
|
||||
* 0x0867 Trap messages, one per block
|
||||
* 0x0868 Wall texts
|
||||
* 0x0869 Switch/Panel descriptions
|
||||
* 0x086A Texture descriptions (Note: From block 273 onwards of the 512 blocks, the text is always "bug")
|
||||
* 0x086B "Can't use X" texts for textures (Note: bug texts are simply "can't be used")
|
||||
* 0x086C HUD texts/messages
|
||||
* 0x086D Object short names
|
||||
* 0x086E Messages of the targeting unit
|
||||
* 0x086F HUD messages (top)
|
||||
* 0x0870 Log category titles ("Level 1 Logs"...)
|
||||
* 0x0871 Action messages
|
||||
* 0x0872 Intro cutscene subtitles
|
||||
* 0x0873 Death cutscene subtitles
|
||||
* 0x0874 Win cutscene subtitles
|
||||
* 0x0875 System scanner label texts
|
||||
* 0x0876 Sign/Logo names
|
||||
* 0x0877 Monitor/Screen texts
|
||||
* 0x0878 Cyberspace toggle texts
|
||||
* 0x0879 Access card names
|
||||
* 0x087A Datalet messages (cyberspace nodes)
|
||||
* 0x087B Menu texts
|
||||
* 0x087C Credits
|
||||
* 0x087D Keyboard help
|
||||
* 0x087E Various HUD messages
|
||||
* 0x087F Tooltip texts
|
||||
* 0x0880 Main menu texts
|
||||
* 0x0881 Endgame statistics texts
|
||||
* 0x0882 Inventory description/version texts
|
||||
* 0x0883 Texts for MFD games
|
||||
|
||||
* 0x0024 Object names (readable)
|
||||
|
||||
* 0x003C - 0x0046 Paper text messages
|
||||
|
||||
#### [Electronic Messages](../content/ElectronicMessages.md)
|
||||
|
||||
* 0x0989 - 0x09B6 E-Mails
|
||||
* 0x09B8 - 0x09BD Level R logs
|
||||
* 0x09C8 - 0x09D7 Level 1 Logs
|
||||
* 0x09D8 - 0x09E4 ...
|
||||
* 0x09E8 - 0x09F0
|
||||
* 0x09F8 - 0x09FE
|
||||
* 0x0A08 - 0x0A13
|
||||
* 0x0A18 - 0x0A21
|
||||
* 0x0A28 - 0x0A30
|
||||
* 0x0A38 - 0x0A3D Level 8 logs
|
||||
* 0x0A98 - 0x0AA4 Data fragments
|
||||
@@ -0,0 +1,57 @@
|
||||
## Video Clips
|
||||
|
||||
Video clips are made out of a sequence of standard [bitmaps](Bitmaps.md). The meta-information about a video clip
|
||||
is stored in resources of type ```0x04```. This information block refers to the resource that contains the frames, which
|
||||
is stored in the same resource file.
|
||||
|
||||
Contrary to [MOVI Resources](moviResources.md), video clips contain only the frame information - nothing else.
|
||||
|
||||
### Format
|
||||
|
||||
**Video Clip Sequence Description** (16+5*N bytes)
|
||||
|
||||
0000 int16 Width of video.
|
||||
0002 int16 Height of video.
|
||||
0004 int16 Resource ID of frames, referring to a compound resource
|
||||
0006 [6]byte Unknown. Always 0x00
|
||||
000C int16 Unknown. TriOp intro: 0x0001, 0x0000 otherwise
|
||||
000E N*[5]byte Sub-table of N sequence entries
|
||||
MMMM int16 Unknown. Always 0x010C
|
||||
|
||||
**Video Clip Sequence Entry** (5 bytes)
|
||||
|
||||
0000 byte Unknown. Always 0x04.
|
||||
0001 byte First frame
|
||||
0002 byte Last frame
|
||||
0003 int16 Frame time (in milliseconds)
|
||||
|
||||
|
||||
### Video Mails
|
||||
|
||||
Video mails are small animated movies sent as mail during the game, all stored in ```vidmail.res```.
|
||||
|
||||
A single video mail is split up in several sequences. Most notably, the TriOp intro is a reused sequence for all mails.
|
||||
The resource file contains 12 such sequences: Per sequence there is one resource of type ```0x04```
|
||||
and a corresponding bitmap resource (containing the frames in blocks).
|
||||
|
||||
Video mails have a size of 200x100 pixel and are the same for the HD and CD releases. They share the palette of the
|
||||
game (```gamepal.res```).
|
||||
|
||||
#### Hardcoded constants
|
||||
|
||||
The classic engine has the following hardcoded constants:
|
||||
|
||||
* There are 6 video mails, ordered as: "shield", "grove", "bridge", "laser", "explode", and "status"
|
||||
* "laser" has two sequences, "explode" has five sequences. The twelth sequence is the intro, having index 10, right before the status.
|
||||
* The first ID for the sequence descriptions is `0x0A4C`
|
||||
* The first ID for the sequence bitmaps is `0x0A40`
|
||||
|
||||
> The engine always plays the intro first, then the requested video mail. The bundling of sequences (like for "explode") is hardcoded,
|
||||
> so if another video mail could either split itself up, or simply have only one frame (or none at all) at the end.
|
||||
|
||||
### Cutscenes
|
||||
|
||||
The files ```start1.res```, ```death.res``` and ```win1.res``` contain low-res variants of the corresponding
|
||||
cutscenes.
|
||||
|
||||
The palettes for these cutscenes are stored in ```cutspal.res```.
|
||||
@@ -0,0 +1,258 @@
|
||||
## MOVI Resources
|
||||
|
||||
Resources with content type `0x11` are a media container themselves, similar to audio/video container formats.
|
||||
These resources are called "MOVI Resources" since the initial tag is the four letter code `MOVI`.
|
||||
|
||||
### Format
|
||||
|
||||
Such a resource contains the following components:
|
||||
* a header, describing meta information about the media,
|
||||
* a palette, with initial colours,
|
||||
* an index, describing the following data entries, and
|
||||
* the data entries.
|
||||
|
||||
**MOVI Header** (`MovieHeader` struct) (1024 bytes)
|
||||
|
||||
0000 uint32 magicId Container tag 0x49564F4D ("MOVI")
|
||||
0004 int32 numChunks Number of chunk entries in file
|
||||
0008 int32 sizeChunks Size of index table
|
||||
000C int32 sizeData Size of content (all data entries)
|
||||
0010 fix totalTime Length of media (in seconds)
|
||||
0014 fix frameRate Frame rate (informational only)
|
||||
0018 int16 frameWidht Width of video
|
||||
001A int16 frameHeight Height of video
|
||||
001C int16 gfxNumBits For videos may be 0x0008, 0x000F or 0x0018, 0x0000 otherwise
|
||||
001E int16 isPalette Palette presence in file. For videos 0x0001, 0x0000 otherwise
|
||||
0020 int16 audioNumChans Numbers of audiochannels 0x0000 - no audio, 0x0001 - mono, 0x0002 stereo
|
||||
0022 int16 audioSampleSize Audio sample size, 0x0001 - 8-bit, 0x0002 - 16-bit
|
||||
0026 fix audioSampleRate Sample rate of audio, in Hz (0x2B770000 - 11127 Hz, 0x56EE0000 - 22254 Hz)
|
||||
0030 uint8[216] reserved Reserved
|
||||
0108 uint8[768] palette Palette
|
||||
|
||||
If the index table size is greater than the total of index entry number times one entry size, the remaining bytes are zero.
|
||||
|
||||
> The index table sizes come in multiples of 0x0400. The rough rule for recreating the existing index sizes is:
|
||||
> Required size less than 0x0400 -> Use 0x0400. Otherwise: Round up to next 0x0400 border and add another 0x0400.
|
||||
|
||||
**Palette** (256 * 3 bytes)
|
||||
|
||||
The palette is always present, even if the MOVI contains only audio. In such cases all the colour channels are 0x00.
|
||||
|
||||
**Movie chunk Entry** (`MovieChunk` struct) (8 bytes)
|
||||
|
||||
0000 uint32 Chunk info (bitfield)
|
||||
0004 uint32 offset Offset to data (from beginning)
|
||||
|
||||
First 4 bytes are uint32 bit field which follow structure:
|
||||
|
||||
bits 00-23 24 time Fixed point timestamp from movie start (in seconds)
|
||||
bits 24-24 1 played Has this chunk been clocked out? (Used by engine internally)
|
||||
bits 25-28 4 flags Chunk type specific flags
|
||||
bits 39-31 3 chunkType Chunk type (see below)
|
||||
|
||||
**Chunk type specific flags** may be:
|
||||
|
||||
For Video chunk type (0x01 MOVIE_CHUNK_VIDEO)
|
||||
|
||||
0x0F MOVIE_FVIDEO_BMTMASK 4 bits of flags is bmtype
|
||||
0x0F MOVIE_FVIDEO_BMF_4X4 4x4 movie format
|
||||
|
||||
> Not clear, why those flags uses same code, this may be bug or leftovers from reusing library component
|
||||
|
||||
For Palette chunk type (0x04 MOVIE_CHUNK_PALETTE)
|
||||
|
||||
0x00 MOVIE_FPAL_SET Set palette from data
|
||||
0x01 MOVIE_FPAL_BLACK Set palette to black
|
||||
0x07 MOVIE_FPAL_EFFECTMASK 4 bits of flags is effect
|
||||
0x08 MOVIE_FPAL_CLEAR If bit set, clear screen
|
||||
|
||||
For Table chunk type (0x05 MOVIE_CHUNK_TABLE)
|
||||
|
||||
0x01 MOVIE_FTABLE_COLORSET Table is color set
|
||||
0x02 MOVIE_FTABLE_HUFFTAB Huffman table (compressed)
|
||||
|
||||
### Chunk Types
|
||||
|
||||
#### 0 End of chunk (MOVIE_CHUNK_END)
|
||||
|
||||
This type is always present as the last entry in the index. It is used to calculate the length of the previous entry as
|
||||
the table does not contain a length field for entries.
|
||||
|
||||
The timestamp of this entry should match the media length from the header.
|
||||
|
||||
#### 1 Video (MOVIE_CHUNK_VIDEO)
|
||||
|
||||
Video frames are compressed in two variants, for low and high resolution.
|
||||
|
||||
Frames are either "full" frames, which set all, or nearly all, pixels in the buffer, typically at a scene change. Other frames are "delta" frames, which re-use (most of) the previous pixel in the buffer. This re-use is done by writing/using the palete index 0x00, which is meant to be transparent.
|
||||
|
||||
##### Low-resolution Video
|
||||
|
||||
Low-resolution video is using type `0x21`. Data contains a bounding box and then the compressed frame using the [compression algorithm](./Bitmaps.md#pixel-compression) for standard bitmaps.
|
||||
|
||||
**Low Resolution Video Data** (8+N bytes)
|
||||
|
||||
0000 [4]int16 Bounding Box
|
||||
0008 []byte Compressed pixel data
|
||||
|
||||
> In the existing videos, the bounding box is always `0, 0, 320, 150`, specifying the same size as the video itself.
|
||||
|
||||
##### High-resolution Video
|
||||
|
||||
High-resolution video is using type `0x79` with a more complex compression algorithm. This algorithm works in conjunction of the `Table` types. See [below](#high-resolution-video-compression) for details on the algorithm.
|
||||
|
||||
**High Resolution Video Data** (2+N bytes)
|
||||
|
||||
0000 int16 Offset to Mask-stream in bytes, from beginning (XXXX)
|
||||
0002 []byte Bitstream
|
||||
XXXX []byte Mask-stream
|
||||
|
||||
The `Bitstream` is a stream of serialized big-endian integers. The `Mask-stream` is a stream of serialized little-endian integers of different lengths (2, 4, 6, and 8 bytes).
|
||||
|
||||
The order and layout of the values in the streams is determined by the algorithm. The decoder will want to read past the end of the streams in a few cases. For these cases the missing bits/bytes are to be set to zero. The encoder removed any trailing 0x00 bytes from these streams in order to save further space.
|
||||
|
||||
#### 2 Audio (MOVIE_CHUNK_AUDIO)
|
||||
|
||||
The data entry contains unsigned 8-bit PCM samples.
|
||||
|
||||
> Audio is chunked into entries of 8192 bytes, even if the MOVI contains only audio.
|
||||
|
||||
#### 3 Text (MOVIE_CHUNK_TEXT)
|
||||
|
||||
**Subtitle Entry** (`MovieTextItem` struct) (16+N bytes)
|
||||
|
||||
0000 uint32 tag Subtitle Control
|
||||
0004 uint32 offset Offset to text string, always 0x10
|
||||
0008 [8]byte Unused -- always 0x00, as they are skipped
|
||||
0010 []byte Null terminated string
|
||||
|
||||
Subtitle text will be shown with the color from palette index 255 (last entry).
|
||||
|
||||
##### Subtitle Controls
|
||||
|
||||
`'AREA'` (uint32 `0x41455241`) is for setting up the subtitle space. It defines the rectangle, in pixel (left, top, right, bottom), where the text is to be displayed. Example:
|
||||
|
||||
```
|
||||
20 365 620 395 CLR
|
||||
```
|
||||
|
||||
`'STD '` (uint32 `0x20445453`), `'FRN '` (uint32 `0x204E5246`) and `'GER '` (uint32 `0x20524547`) specify the actual subtitle text in the respective language, with `'STD '` being the default language (English).
|
||||
|
||||
#### 4 Palette (MOVIE_CHUNK_PALETTE)
|
||||
|
||||
There are two palette entry types: `0x4C` and `0x04`. For any change in the palette, two entries are in the container. Both entries always come in sequence (first `0x4C`, then `0x04`) and both have identical timestamp values.
|
||||
|
||||
The entry with type `0x4C` will have a length of 0 and the same data offset as the next entry, `0x04`.
|
||||
The entry with type `0x04` points to data of 0x300 bytes (= 256*3) which describes the new palette for upcoming frames.
|
||||
|
||||
> At least for high-resolution videos, the next frame after a palette change does not always entirely set the complete pixel buffer for the next frame.
|
||||
> In the intro video for instance, SHODAN's gaining of conscience scene has a few pixel left over from the previous scene.
|
||||
>
|
||||
> As a recommendation, a decoder should wipe the current frame buffer with 0x00 before applying a new palette/drawing further frames.
|
||||
> An alternative could be to remap all pixel values with palette indices as close as possible to the new palette, though this might alter the resulting frame too much.
|
||||
|
||||
#### 5 Table (MOVIE_CHUNK_TABLE)
|
||||
|
||||
Table entries are used in combination with video type `0x79` entries for high-resolution videos. There are two table types:
|
||||
* `0x05`: Palette lookup list
|
||||
* `0x0D`: Control table
|
||||
|
||||
See [below](#high-resolution-video-compression) for details on the algorithm.
|
||||
|
||||
Such entries are common to several frames. For any change, two entries are in the container. Both entries always come in sequence (first `0x05`, then `0x0D`).
|
||||
|
||||
> In the existing files, a change of tables is always followed by a change of palette. The exception is the first scene, which uses the initial palette from the MOVI header.
|
||||
|
||||
##### Palette lookup list
|
||||
|
||||
This entry, with type `0x05` is a simple lookup list. Every entry of type byte is a palette index.
|
||||
This list is truncated as well. The decoder will want to read past the end of this stream, in which case zero bytes must be returned.
|
||||
|
||||
##### Packed Control Words
|
||||
|
||||
Table type `0x0D` contains a runlength encoded list of control words.
|
||||
|
||||
**Packed Control Words** (4+(N*4) bytes)
|
||||
|
||||
0000 int32 Unpacked size
|
||||
0004 []Packed Packed entries
|
||||
|
||||
The `Unpacked size` field equals the number of control words, times three (specifying the size in bytes).
|
||||
The remainder of the entry is then the list of packed control words, from which the actual list of control words is unpacked.
|
||||
|
||||
**Packed Entry** (4 bytes)
|
||||
|
||||
0000 byte Word count
|
||||
0001 uint24 Control Word
|
||||
|
||||
The field `Word count` specifies how often the `Control Word` shall be extracted. A value of 0 is never encountered.
|
||||
|
||||
### High-resolution Video Compression
|
||||
|
||||
High-resolution video compression uses scene-specific tables shared amongst several frames and frame-specific bit- and mask-streams. Frames in this compression are made up of tiles with a size of 4x4 pixel each. For the high-resolution videos of 600x300 pixel this means 150x75 tiles. Tiles are coloured according to different types of control words, from left to right, top to bottom.
|
||||
|
||||
**Control Word** (3 bytes, masked)
|
||||
|
||||
0xF00000 Count value
|
||||
0x0E0000 Type
|
||||
0x01FFFF Parameter
|
||||
|
||||
|
||||
As a rough guideline, the frame-specific bit-stream provides index values into the control word table. According to the type of the control word, the current tile is coloured either directly, or with the additional help of the mask-stream and palette lookup list.
|
||||
|
||||
A note on the bit-stream: Reading from this stream does not automatically advance the current position. Advancing the bit-stream is a separate operation, which may advance with a different number of bits than were previously read. This may cause re-use of some bits to increase compression.
|
||||
|
||||
As noted above, the bit- and mask-stream, as well as the palette lookup list, have possible trailing zero values removed in the files. When the decoder wants to read beyond their end, they must provide values set to 0.
|
||||
|
||||
|
||||
#### Decoder sequence
|
||||
|
||||
A possible decoder is implemented using the following sequence:
|
||||
|
||||
* Iterate over the tiles, outer loop is the rows, inner loop the columns. Finish the loops if either all tiles are covered, or the bit-stream has been exhausted. The stream is exhausted if the current position is at the end of or beyond the available range.
|
||||
* Read a 12-bit value from the bit-stream. Use this value as an index into the control word table.
|
||||
* If the `Count value` of the control word is zero
|
||||
* A `Count value` of zero indicates a `Long Offset`. In this case, the `Type` and `Parameter` fields are taken together to form a 20-bit `Long Offset` value.
|
||||
* Advance the bit-stream by 8 bits
|
||||
* Enter a loop as long as the current control word indicates a `Long Offset`.
|
||||
* Advance the bit-stream by 4 bits
|
||||
* Read a 4-bit value from the bit-stream. Add this value to the `Long Offset` of the current control word and use the result as another index into the control word table. The retrieved entry becomes the new current control word.
|
||||
* Advance the bit-stream by the `Count` value of the current control word. This may indicate a different amount of bits than previously read, even less.
|
||||
* If the type of the current control word is `6`, use the previously processed control word as the current one for further processing.
|
||||
* If the type of the current control word is `5`, tiles shall be skipped
|
||||
* Read a 5-bit value from the bit-stream and advance it by 5 bits. This is the `Skip Count` value.
|
||||
* A `Skip Count` of `0x1F` skips the remainder of the current tile row
|
||||
* Any other value skips the given amount of columns, additionally to the current one. A value of 0 skips only the current tile.
|
||||
* Any type in the range of `0` to `4` colours the current tile. See below.
|
||||
* Next loop iteration
|
||||
|
||||
> Type `7` is never encountered. According to the documentation of TSSHP, this has the same meaning as `6`: use previous control word.
|
||||
|
||||
##### Encoder hints
|
||||
|
||||
* Using the previous control word (type `6`) is not allowed for the first tile of a row. It can't repeat the last operation from the previous row.
|
||||
* Usage of "transparency" byte `0x00` is only processed if at the first index of a palette lookup. See below.
|
||||
|
||||
##### Colouring a tile
|
||||
|
||||
To colour a tile, the `Parameter` value of the current control word is used, as well as the `mask-stream` and the `palette lookup list`. The 16 pixel of a tile are coloured from left to right, top to bottom.
|
||||
|
||||
The palette value for a pixel is determined by an index into a small `lookup array` of palette indices. Depending on the type of the control word, this lookup array is either a made up one, or a segment of the `palette lookup list`. The length of a `lookup array` is always a power of 2 and has possible lengths of 2, 4, 8 or 16.
|
||||
|
||||
The corresponding index values into such lookup arrays have bit sizes of 1, 2, 3 or 4 bits. The 16 index values for a tile are packed into a `mask integer` of 2, 4, 6 or 8 bytes. Depending on the type of the control word, this `mask integer` is made up or read from the `mask-stream`.
|
||||
|
||||
> For example, a lookup array of 4 palette values requires an index size of 2 bits, resulting in a mask integer of 4 byte.
|
||||
>
|
||||
> For pixel coordinates given in x,y: Mask integer bits 0-1 colour pixel 0,0; mask integer bits 2-3 colour pixel 1,0; ...
|
||||
> mask integer bits 28-29 colour pixel 2,3 and mask integer bits 30-31 colour pixel 3,3.
|
||||
|
||||
|
||||
| Type | Lookup Array | Mask Integer |
|
||||
|:----:|--------------------------------------------------------|-------------------------|
|
||||
| 0 | `[ Parameter >> 0 & 0xFF, Parameter >> 8 & 0xFF ]` | Static `0xAAAA` |
|
||||
| 1 | `[ Parameter >> 0 & 0xFF, Parameter >> 8 & 0xFF ]` | 2 byte from mask-stream |
|
||||
| 2 | Parameter is start index into list, 4 entries | 4 byte from mask-stream |
|
||||
| 3 | Parameter is start index into list, 8 entries | 6 byte from mask-stream |
|
||||
| 4 | Parameter is start index into list, 16 entries | 8 byte from mask-stream |
|
||||
|
||||
If the lookup array index is `0`, and the entry ix `0x00`, use the color from the previous frame.
|
||||
@@ -0,0 +1,7 @@
|
||||
## Music Files
|
||||
|
||||
> For the time being, music files are not covered. For further information, follow these resources:
|
||||
>
|
||||
> SSPLAYER: The random song generator. Available from these links (including source):
|
||||
> * http://www.vgmpf.com/Wiki/index.php?title=System_Shock_Random_Song_Generator
|
||||
> * http://wenchy.net/old/ssplayer.html
|
||||
Reference in New Issue
Block a user