XSYSTEM.TXT 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164
  1. ==============================================================================
  2. XSYSTEM Documentation
  3. Copyright (c) 1994-95 Q Studios Corporation
  4. Contact: Peter Freese
  5. pfreese@qstudios.com or CIS:74170,543
  6. ==============================================================================
  7. This file documents the XSystem used in Blood. The XSystem is a system of
  8. communication between dynamic world objects. A firm grasp of the XSystem is
  9. crucial for Blood level designers. The XSystem provides basic building blocks
  10. for creating simple doors, switches, and platforms, as well as the
  11. flexibility for building extremely complex scenarios and puzzles.
  12. ==============================================================================
  13. Overview
  14. ==============================================================================
  15. XSectors, XWalls, and XSprites
  16. The XSystem is based on extending the three simple object types used
  17. in the Build engine: sectors, walls, and sprites. The extensions to
  18. these are referred to as XSectors, XWalls, and XSprites, or
  19. collectively as XObjects. Internally, the XSystem manages a list of
  20. each of each XObject and maintains links between its related object.
  21. The links are stored in the extra field, which you cannot edit in
  22. MapEdit, but can view with the Tab key in 2D mode.
  23. State
  24. Fundamental to every XObject is the concept of state. In the XSystem,
  25. state is a simple boolean condition: ON or OFF. The meaning of state
  26. changes within different contexts, and can mean such things as open
  27. or closed for a door, alive or dead for a creature, or moving or
  28. still for a platform. For some types of XObjects, the implementation
  29. of state is hardwired, i.e., the meaning of ON and OFF are fixed. In
  30. most cases, however, you are free to manipulate the meaning of the
  31. two states as you see fit. Nevertheless, consistency and protocol
  32. will go a long way towards creating maintainable maps that are easy
  33. to debug. For example, it is recommended that you create doors such
  34. that ON is open, and OFF is closed, but this is by no means enforced.
  35. There are many sector effects that are implicitly tied to state. The
  36. two most commonly used effects, lighting and panning, are both by
  37. default directly controlled by sector state, and you will need to
  38. understand state in order to make full use of these effects.
  39. Simply put, the effect is active when the state is ON, and the effect
  40. is inactive when the state is OFF. This means that the water in a
  41. sector could be made to flow or be still, depending on the sector's
  42. state. In the same way, a sector's lighting effect can be made to go
  43. on and off by changes in the state of the sector. The lighting wave
  44. form (if any) and amount of lighting (positive or negative) are
  45. independently configurable, which means the implementation of ON and
  46. OFF are still up to you.
  47. Switches are XSprites that work by changing their state in response
  48. to some stimulus, such as being pressed by the player, or impacted by
  49. a projectile. Nearly every XObject can change state in this fashion,
  50. although you can also effect state changes through the use of
  51. messages transmitted from one XObject to another.
  52. Triggers
  53. All changes in state ultimately originate as a result of some
  54. physical event, usually an action by the player. These events are
  55. known as triggers, and XObjects can be made sensitive to triggers by
  56. setting the appropriate trigger flags:
  57. [x] Push
  58. [x] Impact
  59. [x] Explode
  60. [x] Pickup
  61. [x] Touch
  62. [x] Sight
  63. [x] Proximity
  64. [x] Enter
  65. [x] Exit
  66. [x] WallPush
  67. The Push trigger flag can be set for all XObjects, and is activated
  68. when the player presses the action key while facing the XObject. The
  69. player must be within a certain distance (currently 64 pixels) in
  70. order to activate the trigger. However, if the player is in an
  71. XSector that has the Push flag set, the trigger can be activated if
  72. no other XObject within push range has the Push flag set. Push
  73. triggers have many uses, such as switches that control other
  74. XObjects, swinging doors, or walls the player can push back.
  75. An Impact trigger is generated when the XObject is hit by a vector
  76. weapon, such as the shotgun or the tommy gun, regardless of whether
  77. the source of the vector was a player or a creature. The Impact
  78. trigger flag can be set for all XObjects. Use the Impact trigger flag
  79. to make glass windows change state (and break) when shot.
  80. The Explode trigger is similar to the Impact trigger, except it is
  81. created when the XObject is affected by an explosion. All XObjects
  82. can have Explode triggers. Explode triggers can be used for walls
  83. that can be demolished with TNT.
  84. The Pickup trigger flag can only be set for XSprites. This trigger is
  85. generated when an item is picked up by a player. If you use the
  86. Pickup trigger, you should use the XSprite to send out a message to
  87. another XObject, since it will be deleted immediately after being
  88. triggered. The Pickup trigger makes it easy to create an ambush
  89. where picking up a crucial item causes doors to open exposing hordes
  90. of enemies. This differs from DOOM, which requires that the player
  91. step into a sector that actuates a trigger. Use of the sprite Pickup
  92. flag is preferable to using an XSector's Enter flag where the intent
  93. is to trigger another XObject when a special item is picked up.
  94. The Touch trigger is generated when the player is standing on (and
  95. being supported by) a particular XSprite. Only XSprites can use Touch
  96. triggers. A good use for Touch triggers is to create a break away
  97. floor section using floor sprites that drops the player into some
  98. other hazard.
  99. The Sight trigger flag allows XSprites to generate a trigger when a
  100. player is visible from the XSprite's location. The visibility test is
  101. computationally expensive, so use this trigger flag very sparingly!
  102. The Proximity trigger flag can be set for XSprites to allow them to
  103. trigger when a Dude (not just players) is within a finite distant
  104. from the XSprite. The dude must be with 64 pixels AND be visible from
  105. the location of the XSprite. The visibility test ensures that
  106. proximity triggers don't get generated for Dudes that are on the
  107. other sides of walls. Proximity triggers are used automatically for
  108. player placed proximity bombs, but you can create preset proximity
  109. bombs with this trigger flag.
  110. XSectors can generate triggers when a player enters and exits a
  111. sector by using the Enter and Exit trigger flags. It is not yet
  112. determined whether teleporting from or dying in a sector constitute
  113. leaving, so be careful when using these flags together not to create
  114. potential deadlocks.
  115. The WallPush is an XSector flag that is the equivalent of setting the
  116. Push trigger flag for all of the outward facing walls of a sector.
  117. Setting the WallPush trigger flag makes it easy to trigger red sector
  118. doors. This Flag may be used in conjunction with the Push flag in
  119. sectors where the intent is to have the player activate the XSector
  120. from the inside or outside.
  121. For most XObjects, the effect of a physical trigger is to toggle the
  122. state of the object. This is not always the case, however, and the
  123. implementation of an XObject's response to a physical trigger is
  124. dependent on the type of XObject. In the descriptions of each
  125. specific XObject type, you can assume that a physical trigger toggles
  126. state unless explicitly stated otherwise.
  127. Keys
  128. You can limit what triggers the player is able to generate by
  129. specifying a key requirement. There are up to 7 different keys that
  130. the player can acquire each level. If the key field is set to a value
  131. other than 0, the XObject will not generate a trigger unless the
  132. player possesses the appropriate key. For example, a wall tile might
  133. possess a key hole. If the player has the silver key, pressing the
  134. action button while facing the wall will open the adjoining door (via
  135. a command message to the door). If the player does not have the
  136. silver key, the door will not open.
  137. Messages
  138. The XSystem enables you to create highly interactive and complex
  139. environments, and the primary mechanism for accomplishing this
  140. complexity is the message system. Every XObject has the ability to
  141. send and receive messages to and from other XObjects. Communication
  142. between XObjects is what allows a wall switch to open a door, a trap
  143. to open upon entering a secret area, or a combination lock to
  144. activate a teleporter.
  145. Communication takes places in the form of commands which can be
  146. broadcast on any of 1023 different 'channels'. Each XObject has a
  147. separate transmit and receive channel, called txID and rxID,
  148. respectively. These can be set to the same channel, but usually they
  149. will be different. Think of the receive channel as the channel that
  150. the XObject is listening to. A message will have as many receivers as
  151. there are listeners. If a command is broadcast on channel 200, then
  152. every other XObject with an rxID of 200 can react to that message.
  153. Different types of XObjects can be listening to channel, and each
  154. react differently on reception of a message.
  155. The conditions for when to transmit a message are defined by an
  156. XObject's Send Mask, which is described later.
  157. Commands
  158. The primary reason for sending a message to an XObject is to alter
  159. the state of the recipient. To that end, there are several different
  160. commands that a message may encapsulate:
  161. OFF
  162. ON
  163. state
  164. toggle
  165. !state
  166. link
  167. LOCK
  168. UNLOCK
  169. *LOCK
  170. The simplest of these are the OFF command and the ON command. As you
  171. would expect, these force the recipient to the specified state. To
  172. turn an XObject ON, send an ON command on the channel to which it is
  173. listening. To turn it OFF, send an OFF command on the same channel.
  174. For example, a wall switch could transmit an ON message on channel
  175. 142 when the player presses the action key on the front of the
  176. switch. An XSector with an rxID of 142 would change from OFF to ON
  177. when receiving the message. If the XSector had a lighting effect
  178. defined, it would be activated by the change in state. This is how
  179. you would create a room with a light switch on the wall.
  180. The state command allows an XObject to transmit an OFF or ON command,
  181. depending on what its current state is. If the XObject is OFF, it
  182. transmits an OFF command. If it is ON, it transmits an ON command.
  183. The state command provides a convenient way to synchronize the states
  184. of two or more XObjects.
  185. Any XObject receiving a toggle command will invert its state. Use
  186. this command when you don't care what the original or resulting state
  187. will be, and you just want to ensure that the receiving XObject
  188. changes state.
  189. The !state (read "not state") works similar to the state command,
  190. except the state of the sender is inverted. If it is OFF, it
  191. transmits an ON command. If it is ON, it transmits an OFF command.
  192. The link command is used to synchronize the state of two or more
  193. XObjects at a more fundamental level than the state command, and is
  194. described in detail under "Linking".
  195. Locking
  196. The LOCK and UNLOCK commands alter the state of the recipients locked
  197. status. When an XObject is locked, it will ignore any physical
  198. triggers sent to it. It will still respond to any messages it
  199. receives. The *LOCK command will toggle the locked state of the objects
  200. recieving the message.
  201. System Channels
  202. Channels 0 - 99 are system channels and are reserved for certain global
  203. tasks. Some of these should be transmitted on to trigger global events,
  204. and others can only be received.
  205. Here are the uses of the system channels:
  206. 0 Null channel. No commands are ever sent on channel 0.
  207. 1 RESERVED
  208. 2 RESERVED
  209. tx ÿ3 Voice/text over
  210. tx 4 End level A
  211. tx 5 End level B
  212. tx 6 Lightning
  213. rx 7 Called at startup
  214. rx 8 Called at BloodBath startup
  215. rx 9 Called at Coop startup
  216. 10..89 RESERVED
  217. 90..99 Used internally for remote detonators
  218. tx/rx 100+ Miscellaneous level channels
  219. Channels from 100 to 1023 are free and should be used by the level
  220. designer for communication between XObjects. The uses of the system
  221. channels is further described in the section on System Triggers.
  222. Send Flags
  223. XObjects broadcast messages as a result of a state change. You can
  224. specify which state changes will cause the XObject to transmit by the
  225. send flags:
  226. [x] going ON
  227. [x] going OFF
  228. When the state changes from OFF to ON, a message will be broadcast if
  229. the "going ON" flag is set. When the state changes from ON to OFF, a
  230. message will be sent if the "going OFF" flag is set. If neither flag
  231. is set, the XObject will not broadcast any messages as a result of
  232. state changes. If both flags are set, it will broadcast at any state
  233. change.
  234. For example, suppose you want to use a lever to control a portcullis.
  235. When the lever is pulled one way, you want it to raise the
  236. portcullis, and when it is pulled the other way, you want to lower
  237. the portcullis. You would set the command to "state" and set both
  238. send flags, so the level would send an ON or OFF command every time
  239. the lever is moved.
  240. If, on the other hand, you wanted to use two switches to control the
  241. portcullis, you might have switch A raise the portcullis when it is
  242. turned on, and switch B lower it when turned off. In this case you
  243. would set switch A's "going ON" send flag and set its command to
  244. "ON"; and switch B's "going OFF" send flag and set its command to
  245. "OFF". Switch A would then send an ON command only when its state
  246. changed to ON, and switch B would send an OFF command only when its
  247. state changed to OFF.
  248. The Busy state
  249. For many XObjects, such as doors or lifts, state is used to indicate
  250. one of two spatial positions that it can move between. By definition,
  251. however, transitions between the two states cannot occur
  252. instantaneously, but must progress over some finite period of time.
  253. In this case, the state change will not be considered complete until
  254. the object reaches its destination.
  255. While the object is undergoing a state change, the state field will
  256. remain unchanged, but an internal variable, called "busy" will track
  257. the progress of the state change. The busy value is a binary fraction
  258. that ranges from 0 (OFF) to 1 (ON). You can control how long the
  259. state change takes (for the appropriate XObject types) by specifying
  260. a value for busyTime in 1/10ths of a second. A door with a busy time
  261. of 50 will take 5.0 seconds to open or close. The current maximimum
  262. busyTime is 25.5 seconds, though this may be raised to accommodate
  263. the longer waitTimes used with Momentary Switches.
  264. Once the object reaches its goal state, the state field is changed,
  265. and a message is broadcast, depending on the send flags. The effect
  266. of delaying the state change until transition is complete allows
  267. actions of objects to be sequenced.
  268. For example, imagine what is necessary to move a boat through a set
  269. of locks. First one door opens, and when the door is completely open,
  270. it sends a message to the boat to move it through the door. When the
  271. boat reaches it's destination, it sends a message to the door, which
  272. starts closing. Once the door is closed, it sends a message to the
  273. sector, which raises the water level. When the water reaches its
  274. desired level, it sends a message to the other door, etc.
  275. Callbacks
  276. For many of the XObjects in a level, you will want them to be reset
  277. after a period of time. For example, you might want to create a
  278. vertical door that closes automatically after being open for 10
  279. seconds. The XSystem supports this through the use of callbacks.
  280. Callbacks are a special message type that is generated internally and
  281. gets delivered to the XObject after a time period that you specify.
  282. You control the generation of callbacks through two fields, the
  283. waitTime and the restState. If waitTime is 0, the XObject will not
  284. generate a callback, otherwise it specifies the delay in 1/10ths of a
  285. second between a state change and receiving the callback. The
  286. restState is either OFF or ON, and indicates the default "resting"
  287. state for the XObject. It will post a callback when changing away
  288. from the restState, and when it receives the callback message, it
  289. will set its state to the restState.
  290. In the above example of a vertical door that closes after 10 seconds,
  291. you would create a door such that OFF is closed, and ON is open. Set
  292. the waitTime to 100, and the restState to OFF. Whenever the door
  293. opens, changing state from OFF to ON, it will post a callback message
  294. to itself. After 10.0 seconds, the callback is delivered, and the
  295. door will close.
  296. Unlike broadcast messages which are sent out on a particular channel,
  297. callbacks are delivered directly to the XObject which generated them,
  298. and are not concerned with rxID or txID. Callbacks also work
  299. irrespective of the XObject's send flags. This allows callbacks to
  300. work independently of any other messaging you might involve the
  301. XObject in. You can still broadcast messages on a state change,
  302. regardless of whether that state change occured as a result of a
  303. physical trigger, a command message, or a callback message.
  304. In most cases you will want to leave restState at its default value
  305. of FALSE. There are a few cases where having a restState of ON can
  306. solve some rather unusual design problems, but a description here
  307. would only be confusing. It will suffice to say that you'll know when
  308. you need to change it.
  309. Linking
  310. Imagine opening the door to a dark closet, and as the door opens, the
  311. interior of the closet gets brighter. Imagine raising a flood gate,
  312. and as the gate opens, the water downstream begins to move, slowly at
  313. first, but them more rapidly as the gate gets higher. These are some
  314. of the effects you can accomplish with link messages.
  315. The link command essentially allows an XObject, a master, to
  316. broadcast its busy state. It is not necessary to set send flags for
  317. the link command. The link command will be sent out continuously as
  318. the master changes state. This will cause any XObjects receiving the
  319. link commands, slaves, to synchronize with the master by copying the
  320. master's busy value. When the master finishes its transition, its
  321. state field will change, and so too will that of all the slaves.
  322. The interpretation of the busy value will depend entirely on the type
  323. of XObject receiving the command. Certain sector attributes, such as
  324. lighting amplitude and pan velocity are by default controlled by
  325. state, and therefore busy value. Sending link commands from a door
  326. XSector to a room XSector is an easy to synchronize the illumination
  327. of the room with how far the door is open.
  328. The XSystem makes no checks for slaves starting out in the same state
  329. as masters. If a slave is ON and the master is OFF when a map is
  330. loaded, and the master broadcasts a link command as it changes state
  331. from OFF to ON, the slave will seem to 'pop' to OFF when it receives
  332. the first link command, and then slowly change to the ON state
  333. simultaneously with the master. You should avoid this by ensuring
  334. that slaves start out in the same state as masters.
  335. Decoupling
  336. Each XObject can be thought of as having several components: a
  337. component which handles state and the sending and receiving of
  338. messages, a component which interprets and implements state in an
  339. object specific way, and a part which detects physical triggers.
  340. Normally, these components all function as a single unit. When an
  341. XObject is triggered, its state is modified, the physical
  342. representation changes, and a message may be sent out. This 'unit'
  343. functionality is intuitive, and it makes creating the most common
  344. types of XObjects quite simple.
  345. Suppose, however, that you want to control the lighting in a room
  346. with a wall switch, but you also want to be able to detect when a
  347. player enters the room in order to trigger some sort of trap. You
  348. might set up a static lighting effect controlled by state, so that
  349. when the sector is ON the room is bright and when it is OFF the room
  350. is dark. Pressing a wall switch could send a toggle command to the
  351. room XSector, turning the lights on and off. If you simply set the
  352. Enter trigger flag in the sector, then a player entering the room
  353. would toggle the state of the sector, turning the lights on or off.
  354. And any message sent out would have to depend on a state change,
  355. which would mean it would be triggered not only by physical
  356. triggers, but by state changes caused by the light switch.
  357. Fortunately, there is a way to isolate the functioning of the
  358. XObject's physical trigger component from its state mechanism. The
  359. decouple bit, when set, causes physical triggers not to affect the
  360. XObject's state, and to directly generate a physical trigger message.
  361. This message is broadcast on the txID channel, and causes the
  362. physical trigger to be applied to all receiving XObjects. In other
  363. words, to any XObject receiving the message, the trigger will be
  364. handled exactliy as if it were generated by that XObject itself.
  365. ==============================================================================
  366. XSPRITES
  367. ==============================================================================
  368. Data1 .. Data3
  369. The data fields are a catch all storage area for miscellaneous data
  370. with no place to go. Their use is type dependant.
  371. Difficulty
  372. This specifies at what difficulty level the object appears. Level 0
  373. is the easiest, and level 3 is the hardest. Not yet implemented.
  374. Detail
  375. Not yet implemented.
  376. Map flags
  377. ( ) when seen
  378. ( ) never
  379. ( ) initial
  380. ( ) secret
  381. These allow you to specify the conditions under which the object will
  382. be visible on the players 2D map. The default is "when seen", which
  383. means that it must be first seen in 3D mode before it will be
  384. displayed on the map. XSprites marked as "never" will be invisible
  385. in 2D map mode. To have an XSprite start on the map, use "initial".
  386. "Secret" is not yet defined.
  387. Sound kit
  388. Not yet implemented. See Ideas section.
  389. Respawn flags
  390. Not yet implemented. See Ideas section.
  391. XSprite types
  392. Markers
  393. None implemented yet.
  394. Switches
  395. Toggle Switches:
  396. The most basic of all switch types. It will display as one of two
  397. pictures in 3D mode, depending on the state. The picnum should be set
  398. to the OFF state picture. The ON picture (picnum + 1) will be displayed
  399. when the switch is on. All physical triggers toggle the state of the
  400. Toggle switch.
  401. Momentary Switches:
  402. Like the Toggle switch, except physical triggers can only change its
  403. state to ON. You'll need a callback or a message from another XObject
  404. to reset the switch to the OFF position.
  405. Combination Switches:
  406. Combination switches are multi-way switches which change to an ON state
  407. when they are set to a certain combination. These switches can be used
  408. for combination locks, or even counters, as I will demonstrate. Their
  409. behavior is controlled through 3 data fields:
  410. data1 Current value ( 0 <= x < N-1 )
  411. data2 Key value
  412. data3 Number of values (N)
  413. The switch can have a value from 0 to N-1, where N is specified in the
  414. data3 field. If data3 = 5, for example, the switch can have a value
  415. from 0 to 4, for a total of different values, or positions. Each value
  416. is represented by a different tile. You specify the base tile, which
  417. is the picture it will have when value = 0. For example, if you pick
  418. tile 2300 for the switch, and data3 = 5, the switch will cycle through
  419. tiles 2300-2304.
  420. The current value for the switch is specified in the data1 field.
  421. Normally value is manipulated by the program, but you can set the
  422. initial value so when the map starts a switch will be in a particular
  423. position.
  424. If you enable a trigger for a combination switch, such as the Push
  425. trigger, whenever the trigger occurs the value (data1) for the switch
  426. will increment, wrapping around if it reaches N (data3). In this way
  427. you can cycle continuously through all the different combinations for a
  428. particular switch.
  429. You can also control a combination switch with messages. By sending an
  430. ON command to a combination switch, it will cycle UP. By sending an
  431. OFF command to a combination switch, it will cycle DOWN. In this
  432. manner, you can create a counter. The switch will have a value equal
  433. to the number of ON messages it has received, minus the number of OFF
  434. messages, assuming it starts out with a value of 0 and you don't have
  435. any physical triggers enabled.
  436. The real power of combination switches comes from the ability to set a
  437. key value in the data2 field. The switch will changes its state
  438. depending on whether data1 = data2. In other words, data2 is the
  439. "combination" of the lock. If data2 = 3, whenever the switch cycles to
  440. 3, its state will change to ON, and whenever it cycles away from 3, its
  441. state will go to OFF.
  442. With this knowledge, you can create a combination lock consisting of
  443. multiple switches like the example in the hallway of FXTEST.MAP. This
  444. combination lock actually consists of 4 combination switches: 3 used as
  445. tumblers, and one used as a counter. The tumblers as set up pretty
  446. much as you would expect. For each, data3 specifies the number of
  447. tiles to cycle through, and data2 specifies the key value for each.
  448. Each tumbler sends State to the counter. Unlike the tumblers, the
  449. counter does not have any physical triggers set, so it is only cycled
  450. by messages it receives from the tumblers. Since each tumbler sends a
  451. State command to the counter, it effectively "counts" how many of the
  452. tumblers are in the correct position to open the door.
  453. Since the door should open only when all three tumblers are in the
  454. correct position, the counter switch has data2 = 3. Thus, when it
  455. reaches a value of 3, it will go to an ON state, and send a message to
  456. the door to open. The data3 field for the counter is set to a
  457. arbitrary high value to prevent the switch from cycling around to 0
  458. before it reaches 3. I just checked the code, and it will work just as
  459. well if data3 = 0. So, if you don't want a counter to "wrap around",
  460. just store a value of 0 in data3. In the example, the counter is
  461. visible so you can see how it works, but you should probably hide it in
  462. the real game maps.
  463. The multi-way door setup in the outside area of FXTEST.MAP is only
  464. slightly more complicated than the combination lock. In this setup,
  465. there are also 4 switches, but 3 of them are hidden by embedding them
  466. in the wall next to each door. The combination switch in the center of
  467. the pool is a Master switch, and the 3 hidden switches are slaves. The
  468. master switch sends Link commands to the 3 slaves. The Master switch is
  469. the only one which responds to physical triggers, in this case, a Push
  470. trigger. Whenever the Master switch cycles to a new value, it sends a
  471. Link command to all the slaves, and they all change to the same value.
  472. The value of data2 is irrelevant for a Master switch, and the value of
  473. data3 is irrelevent for a Slave.
  474. Each slave switch has a key value (data2) set so that whenever the
  475. Master (and all the slaves) cycles to a certain value, it will go ON
  476. and send a message to the door it controls to open. In the example in
  477. FXTEST.MAP, the slaves have key values of 1, 2, and 3, in clockwise
  478. order starting with the west most slave.
  479. There is no limit to the number of Slaves switches you can tie to a
  480. Master. They simply all receive on the same channel the Master
  481. transmits on. There is also no limit to the number of tumblers you can
  482. use in creating a combination lock.
  483. Weapons
  484. Ammo
  485. Keys
  486. Items
  487. Dudes
  488. Creatures can use their state to indicate whether they are alive or
  489. dead. Thus, they can send commands when they are killed. It is also
  490. possible for creatures to respond to command words to change their
  491. state -- ergo, they can be killed and brought back to life by remote
  492. control. Creatures can, of course, have many more states than can be
  493. represented by a simple binary state variable. The state bit here can
  494. be considered to mean active/inactive. For example, a creature could
  495. start out life as an inactive statue, and become animated when the
  496. player reaches a certain location. This has the potential for some
  497. really neat stuff.
  498. A creature with a non-zero value in the key field will drop a key of
  499. the specified ID upon death.
  500. Generators
  501. Timer events are used to generate triggers at regular or semi-regular
  502. intervals.
  503. txID command is broadcast on txID channel at each interval, and
  504. optionally going on or off depending on the sendWhen
  505. parameter.
  506. rxID used to turn the generator on or off.
  507. state on = triggers every busyTime +/- data1 tenths of a second.
  508. off = no triggers generated
  509. command used for trigger generation, and normal messages
  510. sendWhen used only for normal messages, ignored for trigger generation
  511. busyTime trigger interval in tenths of a second.
  512. If busyTime is zero then the object will activate only once
  513. for each trigger on.
  514. waitTime time before shutting off
  515. data1 random interval, added or subtracted from data1.
  516. data2 reserved for specific generator types (see kGenFireball)
  517. data3 used internally as callback semaphore to prevent multiple callbacks
  518. What all this means is that the kGenTrigger type, and future
  519. generator types, support being turned on and off by other triggers
  520. (like switches), or OFF by its own waitTime.
  521. The specified command is sent on the specified txID at specified
  522. (busyTime +|- data1) intervals while the kGenTrigger object's state is
  523. ON, regardless of what the sendWhen parameter is set to.
  524. The kGenTrigger will also send the specified command on the specified
  525. txID when the state is turned ON or OFF, if one or both of the
  526. sendWhen fields are set.
  527. kGenFireball
  528. data2 == 0 : no animation, shoots fireball immediately
  529. data2 == 1 : gargoyle "green man" sequence triggers fireball
  530. data2 == 2 : gargoyle "bat face" sequence triggers fireball
  531. kGenSound
  532. soundID == Sound ID
  533. kGenWaterDrip & kGenBloodDrip
  534. The falling object will automatically determine which splash
  535. and sound to make based on the impacted surface type.
  536. Q. What should these be used for?
  537. A. Almost any event that you want to be triggered repeatedly and
  538. regular intervals. In future versions, specific kGen??? types will be
  539. added to generate blood drips, water drips, fireballs, etc. These
  540. will work in much the same way as kGenTrigger except that they will
  541. spawn a special sprite at each interval instead of sending a message.
  542. Q. What should these NOT be used for?
  543. A. DO NOT use the kGenTrigger object to simulate any continuous
  544. motion. We will be adding a continuous motion feature to some of our
  545. sector effects in the near future. If you use the kGenTrigger feature
  546. to simulate this, you will only be hurting your map and wasting
  547. precious time.
  548. Tricks and traps
  549. Tricks/Traps/Hazards
  550. 80 TNT barrels - large barrels of explosive material. Will blow
  551. up after receiving a certain amount of damage. Blowing up is
  552. considered a state change. You can also blow them up with
  553. command messages.
  554. 81 Floor spike - sort of like a sharp stalagmite. Does damage
  555. when touched. ??? Damage once or continuous
  556. 82 Falling rock trap - several rocks fall to the ground. Needs
  557. to be triggered via command.
  558. 83 Gas emitting statue - when triggered, emits a cloud of
  559. poisonous gas
  560. ==============================================================================
  561. XWALLS
  562. ==============================================================================
  563. Panning
  564. Types
  565. ==============================================================================
  566. XSECTORS
  567. ==============================================================================
  568. Shade effects
  569. Wave forms
  570. Period
  571. Amplitude
  572. Phase
  573. Panning effects
  574. pan floor
  575. pan ceiling
  576. velocity
  577. angle
  578. Water depth
  579. Underwater
  580. Types
  581. ==============================================================================
  582. SYSTEM TRIGGERS
  583. ==============================================================================
  584. Voice/Text overs
  585. You can specify one of several messages to display during the game by
  586. sending a message on system channel 3. To choose which message is
  587. displayed, set the XObjects Command field to a user ID from 0 to 63.
  588. Corresponding messages must be defined in the map definition (.DEF)
  589. file for each map. Up to 64 messages may be declared in a .DEF file,
  590. using the syntax defined below.
  591. The idea is to provide the ability to present some sort of plot
  592. element during game play. The message would be associated with a
  593. sound effect which would be played on top of the rest of the
  594. music/audio (like Katarn's voice in Dark Forces). This is NOT the way
  595. to create a sound effect that is supposed to come from some location
  596. in the map.
  597. Perhaps we could create a a level definition file (INI file, perhaps)
  598. that would allow level designers to specify the text of messages and
  599. associated sound resource, rather that having a fixed set for the
  600. game.
  601. Using the data field has some problems, since it is needed for some
  602. specific XObject types, such as combination switches.
  603. ==============================================================================
  604. LEVEL DEFINITION FILES
  605. ==============================================================================
  606. A level definition file is used for each level to store information that is not
  607. easily editable with the map editor. The definition file is a plain text file
  608. with a format similar to that of INI files. There is only one anonymous
  609. section, and it consists of various keys.
  610. Author=string
  611. This is where you get to put your name.
  612. Description=string
  613. The long name of your map. Be creative.
  614. Song=string
  615. The name of the music (midi) file for the level. Do NON include
  616. the extension.
  617. Message?=string
  618. Messages generated by voice over triggers. ? is a value 0 to 63.
  619. ==============================================================================
  620. Experimental
  621. ==============================================================================
  622. This section describes new features of the XSystem that are being tested. The
  623. implementation of these is subject to change, so while you are encouraged to
  624. experiment, please do not rely heavily on them heavily.
  625. Fog:
  626. By adding the line "Fog=1" to your level definition file, you can cause
  627. a level to use fog depth cueing instead of the normal light
  628. diminishing. Having fog enabled will dramatically limit the number of
  629. shade levels available. Fog is global for the level, so you will
  630. probably want to consider using it only for an all outdoor level.
  631. Linking:
  632. Sector linking is now working. To link two sectors place an upper link
  633. marker in one, and a lower link marker in the other. The upper link
  634. goes in the sector where you move upward to end up in the other sector,
  635. and the lower link goes in the sector where you can move downward to
  636. enter the other sector. If this seems backward to people, I can change
  637. it.
  638. The markers are paired by specifying a unique value for the data1
  639. field. This value is shown in 2D mode in the editor. There should be
  640. exactly 2 markers for each value, an upper and a lower marker.
  641. When linking two areas, you should either place them very far apart on
  642. the map, or overlap them properly in the XY plane. This will allows 3D
  643. sound effects to either be out of ear shot, or heard correctly,
  644. respectively.
  645. ==============================================================================
  646. Ideas
  647. ==============================================================================
  648. Damage:
  649. Sector damage:
  650. Damage frequency (every n.nn seconds)
  651. [ ] in sector
  652. [ ] on floor
  653. DAMAGE DESCRIPTOR
  654. Damage descriptor
  655. Damage period (every 1/10th seconds)
  656. [ ] Damage on floor only
  657. [ ] Damage only when ON
  658. Damage Descriptor
  659. Type:
  660. Pummel Punch, pummel, impact or crush
  661. Burn Burn from heat or fire
  662. Bullet Bullets or other piercing projectile
  663. Cut Cutting or cleaving from a blade or sharp edge
  664. Stab Stabbing or impaling
  665. Explode Explosion concussion
  666. Gas Poison gas
  667. Drown Lack of air underwater
  668. Sonic
  669. Psyche
  670. Spirit
  671. Magic
  672. Amount:
  673. # hit points
  674. Sound effects
  675. Each sound effect will have the following properties:
  676. Sample length
  677. Sample rate
  678. Looping flag
  679. Sound Kits
  680. Since it would be difficult, if not cumbersome, to assign sounds for
  681. each possible sound effect that an object might make, sound kits
  682. provide a predefined collection of sounds for object state changes.
  683. (0) -> 1
  684. 0 (->) 1 (loop)
  685. 0 -> (1)
  686. (1) -> 0
  687. 1 (->) 0 (loop)
  688. 1 -> (0)
  689. Respawning
  690. permanent // 0=not permanent, 1=permanent (respawn ignored)
  691. respawn // 0=never, 1=always, 2=optional never, 3=optional always
  692. respawnTime // 0=instant, >0=time in tenths of a second,
  693. launchMode // 0=all, 1=bloodbath, 2=ally, 3=ally&bloodbath,
  694. Surface Kits
  695. Surfaces are used to describe the way that materials react to damage,
  696. object collisions, and interaction with the player.
  697. Surfaces have the following properties:
  698. Footfall sound
  699. Impact sound
  700. Impact effect
  701. Predefined surface types are:
  702. Stone
  703. Wood
  704. Dirt
  705. Metal
  706. Water
  707. Lava
  708. Air
  709. Miscellaneous
  710. a boat
  711. mine cart
  712. mausoleum - door opens, and a platform slides out with a body on it
  713. moving platforms, such as one in ShadowWarrior
  714. You walk by a window and hear the sound of rain coming from outside.
  715. Occasionally, the sky flashes, and then you hear the sound of thunder
  716. from far away.
  717. Floor lightning: Connect a bunch of floor sprites together to create
  718. a lightning-like effect. Imagine a guy pounding a staff on the ground,
  719. and lightning radiates outward on the floor from his staff. When it
  720. hits the player it does damage.
  721. Elevators:
  722. At each floor, there is a call switch for the elevator. Pressing the
  723. switch will illuminate a light, which will stay lit until the elevator
  724. arrives. Above or to one side of the elevator is a panel which
  725. displays the current floor the elevator is on. When the elevator
  726. arrives, a door splits open to allow access to the elevator interior.
  727. Once inside the elevator, the player can press one of several floor
  728. buttons.
  729. Elevator is open on same level as player. Player enters. Player
  730. presses action bar => elevator closes, moves to next floor. Player
  731. presses action bar => elevator opens.
  732. Rachel
  733. She will appear, walk towards her target location (a marker sprite),
  734. and then disappear. Any actions you wish her to perform should be
  735. accomplished with the initial trigger.
  736. Sound generator
  737. Place one of these where you want to create a custom sound, e.g., a
  738. creaky floor or mysterious laugh. When it gets triggered, it will
  739. play the sound id specified in its data field. The sprite's waitTime,
  740. if non-zero, specifies that the sound generator is self triggering,
  741. and determines the average period between sounds in 1/10 seconds. The
  742. interval will vary by +/- 50%.
  743. Wall traps
  744. Force field wall. Blocks all movement when energized (including
  745. bullets).
  746. Crushing wall - moves forward until it meets another wall, crushing
  747. anything and anyone in between. Use two opposing walls to make a nice
  748. sandwich.
  749. Swinging pendulum trap. A large bladed pendulum swings out of a niche
  750. in the wall.
  751. Guillotine - huge blade drops from above.
  752. For flexibility, the blade and projectile wall traps are not
  753. self-triggered. You need something else to trigger them. This allows
  754. you to adjust their timing to suit your needs. For example, you can
  755. trigger the razor doors by placing a player-cross trigger (see below)
  756. a short distant before the blade wall. Adjust the distance so that a
  757. player walking at a normal pace gets sliced neatly in two!
  758. Kinetic effects:
  759. warp to marker sprite
  760. warp to sector
  761. stair case sectors
  762. Sinusoidal floor heights
  763. Sinusoidal walls
  764. Collapsing stairs
  765. [x] Drag objects
  766. Container effects:
  767. Teleport
  768. Relocate
  769. Sinking through floor
  770. Linking
  771. Upper linked sector
  772. Lower linker sector
  773. Upper linked water
  774. Lower linked water
  775. Linked sectors are combined vertically so that the ceiling of one is
  776. the floor of another. This means it is possible for the player to move
  777. between them, and to partially be in both.
  778. Teleport when enter once to target location
  779. Teleport when enter always to target location
  780. Combination Switches:
  781. * Counter switches cycled by messages from something other than a
  782. combination switch. For example, you can keep track of the number of
  783. times a Player enters a sector. On the 10th time -- Zap!
  784. * Combination locks with more than one set on combinations. You could
  785. do this by have a set of tumblers which are used as Masters, controlling
  786. several sets of Slaves each with their own combinations. In this
  787. manner, you could have a combination lock which causes one action when
  788. one combination is entered, and another action for a different
  789. combination.
  790. * Combine tumblers with a momentary switch so the Player needs to enter
  791. a combination and then press a switch to perform an action. The
  792. momentary switch would send state when going ON and OFF just like the
  793. tumblers, but would provide an extra value to the count.
  794. * Lots of other cool stuff. These things are really powerful -- there's
  795. an almost unlimited potential in using hidden switches that nobody's
  796. using yet. If you have something you want to try, but can't figure out
  797. how to do it, just tell me and I'll try to create an example for you. I
  798. welcome any challenges!
  799. ==============================================================================
  800. GLOSSARY
  801. ==============================================================================
  802. Dude
  803. Missile
  804. Projectile
  805. Trigger
  806. Vector weapon
  807. ==============================================================================
  808. TROUBLESHOOTING
  809. ==============================================================================
  810. WHY DON'T MY DOORS WORK?
  811. Make sure the doors are receiving triggers. If they are triggered externally,
  812. you need a matching txId->rxId pair. If they are triggered internally, check
  813. your trigger flags. Make sure the sector is not decoupled.
  814. WHY DO DOORS START IN THE WRONG POSITION?
  815. Remember that you must draw your doors in the OPEN position, but set their
  816. state to reflect how you want the door to first appear in the level.
  817. WHY DOES A TEXTURE STRETCH ON A SLIDING DOOR?
  818. You may have an extra wall tagged for movement. If not all your walls move,
  819. then at least some of the wall textures will stretch. Try to make them hidden.
  820. WHY DO DOORS 'POP' FROM OPEN TO CLOSED?
  821. Make sure that busyTime is non-zero.
  822. MOMENTARY SWITCHES DON'T RESET.
  823. Momentary switches do not automatically reset, although you can cause any
  824. XObject to reset to a rest state after a period of time by setting the
  825. waitTime.
  826. ==============================================================================
  827. HISTORY
  828. ==============================================================================
  829. 95/07/13
  830. First official release. The type specific descriptions for XSprites, XWalls,
  831. and XSectors is missing, but the overview is complete and contains the
  832. information that everyone needs. Please address questions or suggestions to
  833. me at the email address in the file header.
  834. -----------------------------------------------------------------------------
  835. 95/12/10
  836. Anybody notice that we haven't been documenting things in here anymore? Me
  837. neither.
  838. The ink was hardly dry on the new locking code when I decided to make a change
  839. which I think will make it more flexible. The locked flag now only prevents
  840. XObjects from responding to physical triggers. They can now still be
  841. controlled with messages.
  842. -----------------------------------------------------------------------------
  843. 95/12/18
  844. Added experimental notes for Fog and linking sectors.
  845. -----------------------------------------------------------------------------
  846. 96/01/17
  847. Added Fireball generators
  848. Added Sound generators
  849. Added WaterDrip generators
  850. -----------------------------------------------------------------------------
  851. 96/01/18
  852. Added MachineGun hazard which can also be destroyed.