home *** CD-ROM | disk | FTP | other *** search
- ===========================================================================
-
- The Unofficial Specs for
- Duke Nukem 3D
-
- V1.1
-
- By Vincent Nguyen Quang Do
- E-Mail : 101366.1734@compuserve.com
- Compuserve: 101366,1734
-
- ===========================================================================
-
- What's new in this version:
-
- - Simply the list of all the keywords and their use. I hadn't the time to
- finish this part when I uploaded the first version.
-
- ===========================================================================
-
- These specs are highly preliminary, and are far from complete. It requires
- a certain programming knowledge to understand what I have written, but
- fortunately, not much.
-
- It is not a complete documentation with every aspect of the script
- language. You have to examine the .CON files for yourself using what you
- have learned from reading this text.
-
- First, with the usual stuff: as stated in the .CON files, Apogee and 3D
- Realms do not support experiments with these files. To be more precise,
- here is the official policy :
-
- " 3D Realms encourages you to experiment freely with the parameters
- contained in this file, and to share your discoveries with the rest of the
- world. However, BE ADVISED that 3D Realms does NOT offer any technical
- support on how to use this file or other user-modifiable features of this
- game. Do NOT call 3D Realms or Apogee Software for advice or help with
- this subject. "
-
- Next thing : I cannot be held responsible for any damage to your softwares,
- hard-drive, computer and anything related to you modifying the .CON files.
- The bottom line is : MAKE BACKUP COPIES FIRST. Although I don't think it
- can be damaging to your hard drive to modify these files, who knows ?
-
- At last, you can distribute this file around you, unless someone from 3D
- Realms or Apogee tells you you can't anymore (they didn't tell me I was
- violating some kind of copyrights, so I assume I can write this specs).
-
- Finally, I am french, so please forgive me for any bad written english.
-
- No let's start with the fun part.
-
-
- ===========================================================================
- PART I : The Basics
-
-
- As many of you probably noticed, when you start Duke Nukem 3D, the game
- starts a compiler that takes as paramater the GAME.CON file in the game
- directory.
-
- The very beginning of this GAME.CON file is the following :
-
- include defs.con
- include user.con
-
- These files are processed first. The defs.con contains all the " define "
- for the game. The user.con contains all the parameters that can be changed
- in the game (damage for each weapon, hitpoints for each monster and so
- on...).
-
- So, we're going to start with the DEFS.CON file. This file is simply a
- bunch of define. Five types of objects are defined in this manner : the
- sprites (more on this later), the basic actions, the weapons, the different
- player actions, the inventory action and the sound effects.
-
-
- Ex :
-
- define FIRSTGUNSPRITE 21
- define CHAINGUNSPRITE 22
- define RPGSPRITE 23
- define FLAMETHROWERSPRITE 24 <= The sprite for the flamethrower
- .
- .
- .
- define face_player 1 <= The basic actions used in the AI code
- define geth 2
- define getv 4
- .
- .
- .
- define KNEE_WEAPON 0 <= Weapon definition
- define PISTOL_WEAPON 1
- define SHOTGUN_WEAPON 2
- define CHAINGUN_WEAPON 3
- define RPG_WEAPON 4
- define HANDBOMB_WEAPON 5
- define SHRINKER_WEAPON 6
- define FLAMETHROWER_WEAPON 7
- define TRIPBOMB_WEAPON 8
-
- define pstanding 1 <= Stands for Player Standing
- define pwalking 2
- define prunning 4
- define pducking 8
- define pfalling 16
- .
- .
- .
- define GET_STEROIDS 0 <= Inventory Actions
- define GET_SHIELD 1
- define GET_SCUBA 2
- define GET_HOLODUKE 3
- .
- .
- .
- define KICK_HIT 0 <= Sound Effects
- define PISTOL_RICOCHET 1
- define PISTOL_BODYHIT 2
- define PISTOL_FIRE 3
- define EJECT_CLIP 4
- define INSERT_CLIP 5
-
-
- The USER.CON file for itself contains all the user modifiable stuff and is
- not very interesting in itself (unless someone tells me he doesn't
- understand anything in the file, I won't write anything more about this
- one).
-
-
- Now for the hard part, and what you've all been waiting for: the GAME.CON
- file
-
- This file is primarly used by DN3D for it's monsters' AI. Modifying this
- file allows for VERY interesting effects, such as creating new monsters ;
- modifying weapons effects, monsters' behavior and so on... Let's start with
- the basic notion of the game.con file : the " actor ".
-
- action RUBCANDENT 1 1 1 1 1
- action RUBCAN
-
- actor RUBBERCAN WEAK
- ifaction RUBCANDENT { ifactioncount 16 { strength 0 action RUBCAN break
- } }
- else ifhitweapon
- {
- ifwasweapon THROWFLAME { state rats ifrnd 48 spawn BURNING debris
- SCRAP3 4 /* spawn EXPLOSION2 */ killit }
- else ifwasweapon RADIUSEXPLOSION { state rats ifrnd 48 spawn
- BURNING debris SCRAP3 12 /* spawn EXPLOSION2 */ killit }
- else action RUBCANDENT
- }
- enda
-
-
- Every object, monster, in short anything Duke can deal with is an actor.
- This actor is referenced in the map by a number. This number is related to
- the bunch of define in the DEFS.CON file. For example, the basic trooper is
- referenced by the LIZTROOP keyword, which in itself is defined as the
- integer 1680 (see the DEFS.CON file). Not only is this number used for
- identification purpose, but also for display purpose. You'll understand
- more about this later.
-
- So, let's suppose you have the actor RUBBERCAN in the map. The above
- definition shows that this RUBBERCAN has 5 hitpoints (keyword WEAK). The
- code within the " actor " and the " enda " keywords defines how the
- RUBBERCAN is handled, in this particular case when it is hit by a weapon.
-
- This code is always running as long as the actor is " alive ", namely it
- hasn't been killed with the " killit " keyword. Now, what can we do with
- this actor, and how are the sprites displayed ? If you take a look at the
- code above, you can see the keyword " ifaction ". Still above, there are
- two action definitions. In fact, an " action " in the .CON files is simply
- a sequence of sprite. As long as the " actor " is performing an action,
- these sprites are displayed in sequence. This speed as well as the
- different sprites of this sequence are determined by the numbers after the
- action name. I'll explain this later with a more interesting actor.
-
- We have here the basic notions of the GAME.CON file. Every object, monster,
- is an ACTOR which is performing a certain ACTION. These ACTION are related
- to the sprites displayed. With the " ifaction " and the " action "
- keywords, the game knows what action the actor is performing, and can
- change this action. On the above example, the script performs the following:
-
- If the RUBBERCAN is performing the RUBBERCANDENT action, then it counts how
- many times (" ifactioncount ") this action has already been processed. If
- this number is below 16, it does nothing and runs again.
- If this number is 16, then it calls the action RUBCAN. The action
- RUBBERCANDENT is associated to the sprites showing the RUBBERCAN with a
- small dent. The action RUBCAN is the standard RUBBERCAN.
-
- If the action is not RUBBERCANDENT, then the script tests if the RUBBERCAN
- was hit by a weapon, and what kind of weapon. If this is an explosion or a
- flamethrower, then the RUBBERCAN is destroyed. Else, the scripts performs
- the RUBBERCANDENT action.
-
- This the very first example of what can be done with the programming
- language. One could for example spawn an ammo if the rubbercan is
- destroyed. Or you could generate a particular sound. Or spawn rats. Or
- anything else comes to mind (almost...)
-
- Let's take a deeper look into the action keyword (you can find the
- following line in the game.con file) :
-
- action ATROOPWALKING 0 4 5 1 12
-
- As stated before, each monster is referenced by a number. For the basic
- trooper, this number is 1680, for the PIGCOP it is 2000. The keyword action
- allows to define what frames are to be displayed when an actor is
- performing a certain action. The first number is the RELATIVE first frame
- number. Why relative ? Simply because to obtain the real sprite number, you
- have to add the actor number, here 1680. The second number is the number of
- frames to be displayed, the third is how many frames you actually skip
- between each frame you actually display, the last is a multiplier (allowing
- to cycle through the frames backward), and the last is a tempo. Hence, the
- above action would display the relative frames 0,5,10 and 15 (add 1680 to
- have the absolute frame). Note that this is a 3D Sprite, so if you turn
- around the monster, you can see different orientation, without changing
- anything in the script.
-
- action ATROOPWALKINGBACK 15 4 5 -1 12
-
- This action would display the frames 15,10,5,0.
-
- The other important keywords are " move ", " ai " and " state ".
-
- move allows to define a speed : " move TROOPWALKVELS 72 "
-
- ai allows to associate an action with a subroutine and a basic action :
- ai AITROOPSEEKENEMY ATROOPWALKING TROOPWALKVELS seekplayer
- ATROOPWALKING is the action
- TROOPWALKVELS is the speed
- seekplayer is a basic action, directly performed by the
- program, without the help of the script. It allows the actor to "move"
- toward the player without having to program everything.
-
-
- As for the "state" keyword, we have to examine more closely the actor :
-
- actor LIZTROOP TROOPSTRENGTH ATROOPSTAND state troopcode enda
-
- LIZTROOP is the actor number (1680), TROOPSTRENGTH is the hitpoints,
- ATROOPSTAND is the first action performed by this actor. The keyword
- "state" calls a kind of sub-routine, defined in the scripts between the
- "state" and "ends" keywords.
-
- Here is the code for this state :
-
- state troopcode fall <= drop an actor to the floor
- ifinwater ifrnd 1 spawn WATERBUBBLE
- ifaction ATROOPSTAND { ifrnd 192 ai AITROOPSHOOTING else ai
- AITROOPSEEKPLAYER }
-
- If the action is ATROOPSTAND, then there is one 3 chances on 4 (192 out of
- 256) that the actor will perform the AI subroutine AITROOPSHOOTING.
- Otherwise it performs the AI subroutine AITROOPSEEKPLAYER.
-
- ifinwater ifrnd 4 spawn WATERBUBBLE
- else ifaction ATROOPPLAYDEAD
- {
- ifhitweapon
- {
- ifwasweapon RADIUSEXPLOSION { sound SQUISHED state
- troop_body_jibs state standard_jibs state delete_enemy }
- break
- }
- else state checksquished
-
- ifcount PLAYDEADTIME { addkills -1 soundonce PRED_ROAM cstat 257
- strength 1 ai AITROOPSHOOTING }
- else ifp pfacing resetcount
-
- break
- }
-
- If the trooper is playing dead, we still have to check wether the lying
- body is destroyed by an explosion or is squished. If the PLAYDEADTIME is
- over, then trooper rises again (with a strength of 1) and tries to shoot
- the player.
-
- else ifaction ATROOPDEAD
- {
- strength 0
- ifrespawn ifcount RESPAWNTIME { spawn TRANSPORTERSTAR cstat 257
- strength TROOPSTRENGTH ai AITROOPSEEKENEMY }
- ifhitweapon
- {
- ifwasweapon RADIUSEXPLOSION { sound SQUISHED state
- troop_body_jibs state standard_jibs state delete_enemy }
- break
- }
- else state checksquished
- break
- }
-
- If the trooper is dead, then it"s strength is zero. The program checks if
- the respawn flag is set, and if so let the trooper rise again. If the body
- is hit by an explosion, then it is definitely "killed"
-
- else ifaction ATROOPSUFFERDEAD
- {
- ifactioncount 2
- {
- ifrnd 64 { resetcount action ATROOPPLAYDEAD }
- else { soundonce PRED_DYING action ATROOPDEAD }
- }
- }
-
- This action is performed when the trooper is shot and is on the ground in
- pain. It has 3 chances out of 4 to die, and one chance to play dead (see
- above)
-
- else ifaction ATROOPDYING { state troopdying break }
- else ifaction ATROOPSUFFERING
- { state troopsufferingstate ifhitweapon state checktroophit break }
- else ifaction ATROOPFLINTCH { ifactioncount 4 ai AITROOPSEEKENEMY }
- else
- {
- ifai AITROOPSEEKPLAYER state troopseekstate
- else ifai AITROOPJETPACK { state troopjetpackstate soundonce
- DUKE_JETPACK_IDLE }
- else ifai AITROOPSEEKENEMY state troopseekstate
- else ifai AITROOPSHOOTING state troopshootstate
- else ifai AITROOPFLEEING state troopfleestate
- else ifai AITROOPFLEEINGBACK state troopfleestate
- else ifai AITROOPDODGE state troopseekstate
- else ifai AITROOPDUCKING state troopduckstate
- else ifai AITROOPSHRUNK state troopshrunkstate
- else ifai AITROOPHIDE { state troophidestate break }
- }
-
- ifhitweapon state checktroophit else state checksquished
- ends
-
- The rest is simple and deals with the other action the trooper can perform.
-
-
- What you must remember :
-
- An action is simply a list of frames. You can make the actor do something
- based upon this action, but it doesnÆt act on itself. You have to
- explicitely use the "ifaction" keyword.
- On the other hand, an AI seems to allow a certain degree of freedom for the
- actor : it does act on it's own... You can however have the actor perform
- something more difficult by using the "ifai" keyword. Note that this is
- purely an hypothesis.
-
- Now, let's go back to the frames. The following action is performed when
- the trooper is effectively dead.
-
- action ATROOPDEAD 54
-
- The relative frame number number 54 (add 1680 for absolute). What happens
- if you change this number ? Well, for example, try 320. Instead of a dead
- body, you have a standing pigcop. Remember the PIGCOP number (2000) ? And
- 2000-1680 happens to be 320... So every sprite can be accessed with this
- method. In fact, remember that even if a body is lying on the ground, it
- still an actor with it's own action and script. I think that the game
- deletes old actor when there are too much actor in the level.
-
- You could also replace the above with
-
- action ATROOPDEAD 0 4 5 1 12
-
- You would have a walking corpse !
-
- What I can tell you is now to experiment. As you can see, it isnÆt a very
- hard language. A few comments though : it seems there are no variables, the
- "ifpdistl" keyword stands for ifplayerdistancelower, and the "ifpdistg"
- stands for iplayerdistancegreater (took a while to figure that one out !)
-
- ===========================================================================
- Part II : Keywords
-
-
- Now that you understand the basic concepts of the script language used in
- Duke Nukem, here is a list off all the keywords with their associated
- effects (at least, those I understood). I hope I won't forget any. If you
- find a mistake, do not hesitate to contact me ! This list is the result of
- many trials and errors, and as such is prone to mistakes. I do not claim to
- have the supreme knowledge. That said, let's go back to our list. When
- necessary, I used the <...> and [...] symbols. What's between the first
- symbols seem to required, while what's between the second symbols is optional.
-
- action <name> ... Define an action and it's associated sprites
- (see above). You can also use this one within a code
- to change the actor's current action.
-
- actor <name> <strength> [actioname] [ai ainame] [statename]
- If you define more the ai and/or the state performed,
- you must end your list with the keyword "enda"
-
- addinventory <object> <quantity> Guess what ? The list of available
- objects is in the defs.con file.
-
- addphealth <no> <no> can be negative. This allows to substract health
- from the player (used in the Octabrain code)
-
- break Forces the program to exit the current function. This
- allows to bypass some code if certain requirements are
- met.
-
- cactor <actor_name> Call an actor. In fact, it only calls the actor code
- not the actor definition (action, ai, and so on)
- This can be used for example when creating multiple
- monsters with the same basic design: you create the
- actors which in turn call the basic actor. To
- understand this better, I suggest you take a look at
- the alien trooper definition.
-
- cstat <no> Change the actor status. I don't have all the numbers
- but here is what I know:
- 32768 hides the sprite (not sure)
- 257 ressurects the actor once more
- 0 kills it
-
- debris <debris_name> <number> Spawns flying debris. The kind of debris is
- defined by debris_name, the number by...
-
- endoflevel <??> This is used when you want the script to end the
- level. Usually when you kill a boss. The number
- following it is unknown to me however. Maybe a tempo ?
-
- else I think this one is quite clear.
-
- fall Apparently, this instantly drops the actor to the
- floor. However, I am not quite sure about this one.
-
- globalsound <sound_name> What's the difference with "sound" and
- "soundonce" ? I don't know.
-
- guts <guts_name> <number> Spawns flying guts. The difference with the
- above is not obvious.
-
- hitradius <range> <strength1> <strength2> <strength3> <strength4>
-
- This generates an explosion. Damage to monsters and
- other players depends of the distance between the
- explosion and these actors. Damages range from
- strength1 to strength4.
-
- ifai <ai_name> Checks whether the actor's current ai is ai_name
- ifaction <action_name> Same thing for the action
-
- ifactioncount <number> When called from within an action, counts the number
- of times this action has been processed and then
- checks whether it is greater than the number.
- If so, it performs the following code.
-
- ifcansee Checks whether the actor can see another actor.
-
- ifcanseetarget Apparently used for inventory items. This checks
- whether the player can see the actor.
-
- ifcanshoottarget Checks whether the actor can shoot the player. This
- usually used with the "ifcansee" keyword.
-
- ifceilingdistl <no> Stands for "If Ceiling Distance Lower Than"
-
- ifcount <number> This one was quite hard to figure out. Apparently, it
- checks whether the time is greater than the number. It
- allows to check whether an actor was kept in a certain
- action.
-
- Ex:
- state genericshrunkcode
- ifcount 32 { ifpdistl RETRIEVEDISTANCE pstomp }
- ...
-
- When a monster is shrunk, it can be squished by the
- player if he steps on it. Raising the number allows
- the monster to survive longer, as the player must stay
- longer within RETRIEVEDDISTANCE to stomp it.
-
- ifdead Checks whether the actor has been killed.
-
- iffloordistl <no> Stands for "If Floor Distance Lower Than"
-
- ifgapzl I wasn't able to figure that one out... I initially
- thought it was "if gap in z coordinate is lower than"
- but it doesn't fit with the main game.con file.
- Any hint would be appreciated...
-
- ifhitspace Checks whether the player hit the spacebar. Allows
- to run a special code in some instances. Ex: when
- there is a water fountain, Duke can drink and gain 1
- health point. This is performed in the game.con file
-
- ifhitweapon If the actor was hit by a weapon, then performs the
- following code
-
- ifinwater Checks whether the actor is underwater
-
- ifmove <no> Checks against <no> what is the speed of the current
- actor.
-
- ifonwater Checks whether the actor is swimming at the surface
-
- ifp Checks something on the player
-
- ifpdistl <no> Stands for "If PLayer Distance Lower than"
- ifpdistg <no> Do you guess that one ?
-
- ifphealthl <no> Stands for "If Player Health Lower Than"
-
- ifrespawn Checks whether the respawn flag is set.
-
- ifrnd <number> Generates a random number and checks whether it is
- lower to the following number. If so, it executes
- the following action.
-
- Ex: ifrnd 192 ai AILIZGETENEMY
-
- If the random number is lower than 192, then the actor
- changes it's ai state to AILIZGETENEMY.
-
- ifspawnedby <actor_name> When you use the "spawn" keyword within an
- actor, the spawned actor keeps in mind what
- spawned it (!!!). You could use this to set
- up traps for players (such as having the ammo
- dropped by a trooper detonate if a player
- tries to pick it up...)
-
- ifspritepal <no> Checks whether the sprite palette is <no>
-
- ifsquished Apparently, this checks whether the actor is squished.
- However, since I don't know what squishing means in
- the game...
-
- ifwasweapon <weapon_type> I think you already guessed that one ?
- Available weapon_type are:
- RPG
- THROWFLAME
- SHRINKSPARK
- RADIUSEXPLOSION
- FIREEXT (??)
- KNEE
- FIRELASER
- COOLEXPLOSION1 (Octabrain Shot)
- SHOTSPARK1
-
- Maybe some more, but they were not used in the
- main script. You could also try the following:
- SHOTGUN
- FIRSTGUN
- ???
-
- include As stuff said, includes another file
-
- killit Erase the current actor from the game. The script for
- this actor no longer runs.
-
- move <speed> [no] Define a speed. Is mainly used with the "ai" keyword.
- However, you can also use it within a state function.
- no is a number that defines a special action performed
- by the actor.
-
- Ex: move TURRVEL face_player
-
- This moves the actor at speed TURRVEL so that it faces
- the player. The list of possible action is in the
- defs.con file.
-
- operate I don't know what this one is used for. It probably
- allows an actor to operate a switch, a door or an
- elevator. However, I've never seen a monster
- performs such a thing. Maybe because when they don't
- see the player, they are as dumb as a wall.
-
- palfrom I must say I don't know how this one works...
-
- palive Checks whether the player is alive. It must be used in
- cunjunction with the "ifp" keyword. The other options
- are: pstanding, pwalking, ... See in the defs.con file
-
- pstomp This one is funny. It is used in the genericshrunk
- code (see above). It shows the player stomping on
- a monster. You can usually use it with very small
- monsters, although it can be also done on big ones,
- if you can manage to climb on one (g).
-
- resetactioncount Reset to Zero the number of times this action has been
- processed.
-
- resetcount Reset to Zero the time check used by "ifcount"
-
- shadeto <no> This in fact dim or brighten the actor, depending on
- the value of <no>. -127 renders (temporarly) the actor
- black, while 127 renders it white. However, I must
- confess I didn't very good results. It seems there is
- a palette involved, and I couldn't determine the
- relationship. The best example is in the Octabrain
- code (JELLYFISH in the script).
-
- shoot <weapon_type> The actor shoots with a weapon. Weapon types include
- the following: FIRELASER
- RPG
- FLAMETHROWER
- MORTER
- CHAINGUN
- SHOTGUN
- There might be some others...
-
- sizeto <nx> <ny> This one is fun. It shrinks the actor at nx/256 and
- ny/256 it's original size. So, if you take 512, you
- would double the size of the actor. However, there
- are a few things to keep in mind when using this.
- First, the shrinking is not instantaneous. It takes a
- while until the corresponding code is performed. If
- you want to shrink an actor, you must always use the
- "ifaction" keyword in order to wait before it does
- anything else. Try it and you'll understand. Second,
- it seems you must periodically resize the actor. If
- you use this keyword just once, then it will revert
- back to it's original size a while after.
-
- sound <sound_name> Generates a sound. The list of available is in the
- defs.con file (I think)
-
- soundonce <sound_name> Also generates a sound, but only once (?)
-
- spawn <actor> Spawns an actor. Note that not every sprite is
- spawnable. It must somehow have been defined as
- spawnable... So you can only spawn existing actor
- and cannot define new ones (using a number above 4000
- for example, as might be hinted by looking at the
- defs.con file)
-
- spritepal <no> Change the palette sprite to the palette no. Usually,
- an actor is always referenced by a number. But there
- is also a palette that can be used for multiple monster
- definition. For example, the trooper captain (with the
- teleporter) is a standard trooper with a different
- palette. You can test what palette the current actor
- has with the "ifspritepal" keyword.
-
- state ... ends Can be used in two manner:
- Defining the function and it's code
- Calling the function. It must have been defined before
- You don't have to use the "ends" keyword when calling
- a state.
-
- strength <number> Defines the actor's strength. Note that you must
- also change the status of the actor using the "cstat"
- keyword if you want to ressurect a monster (see below)
-
- quote <no> This displays the quote number <no>.See in the defs.con
- file for more information.
-
-
- Well, I think that's all. I hope I didn't forget anything. If so, please
- forgive me and give me a call so I can correct my mistake. Any information
- on any of the missing features would be greatly appreciated.
-
- ===========================================================================
- Part III : Some Examples
-
- Why not start with some examples ?
-
- Well, you noticed that sometimes a trooper drops a pistol ammo. Here is the
- code :
-
- state checktroophit
- ifaction ATROOPSUFFERING { stopsound LIZARD_BEG sound PRED_DYING cstat
- 0 strength 0 action ATROOPSUFFERDEAD break }
- ifdead
- {
- state drop_ammo <= Here. It calls the drop_ammo state
- state random_wall_jibs
- addkills 1
-
- Well, you could have it drop a TRIPBOMB, no ? Just add the line
- "spawn TRIPBOMBSPRITE" and there you go, you can pick up a trip bomb.
- Unfortunately, there is no sprite for it in the shareware version, so donÆt
- be surprised if you don't see it, it's normal. Furthermore, you can use it
- only as long as you don't switch to another weapon, because I didn't find a
- way to reselect it.
-
- You can try all the weapons in this manner (SHRINKERSPRITE and
- FLAMETHROWERSPRITE).
-
- You could also have it respawn another monster... such as a PIGCOP, or a
- JELLYFISH (Octabrain), or... a BOSS1 (aaaaargh...).
-
- Better still. You can replace all the basic trooper in the game with a
- PIGCOP. All you have to do is define the PIGCOP ("define PIGCOP 2000" in
- the DEFS.CON file) as number 1680. Of course, you still get the frames for
- the trooper, but it would act like a PIGCOP, and shoot with a shotgun... If
- you want to have the correct frames, you have to modify the pigcop's
- actions and add 320 to each basic frame. But remember that this only deals
- with the standard standing trooper. Ducking trooper and flying trooper
- would remain the same. Until they hit the ground...
-
-
- There are tons of things to experiment. If I have the time, I'll upload a
- few of our creations (a friend and me).
-
- What I need know is FEEDBACK as well as some information on what I didn't
- quite figure out in the language. So if you think you discovered something
- that would be of interest, feel free to write me a little E-mail.
-
- If you have any question, I can be reached at the following E-Mail adress :
- 101366.1734@compuserve.com
-
- Have fun !
-
- Vincent Nguyen Quang Do
-