######################################################################
Quake Console Tutorial
######################################################################

======================================================================
Abstract
======================================================================

Author: JakFrost
Email: jakfrost(at)planetquake(dot)com
Web Site: http://www.planetquake.com/console/
Created: May 2, 1997
Last Modified: May 18, 2000
Based On: WinQuake v1.09
Source: http://www.planetquake.com/console/tutorials/quake.html

Copyright (C) 1997-2000 JakFrost, All Rights Reserved

This document is a tutorial for the Quake console.  It describes all
aspects of the console; such as the syntax, the usage of commands and
variables, the creation of aliases and bindings, and script.  There is
a great amount of information contained in this tutorial which should
help anybody who is willing to read it and learn from it.

======================================================================
Table Of Contents
======================================================================

1. Introduction
2. Console
3. Commands
    3.1. Action
    3.2. Command
    3.3. Toggle
    3.4. Variable
4. Syntax
    4.1. Space
    4.2. Semicolon
    4.3. Double-Quote
    4.4. Double-Slash
5. Bindings
6. Aliases
7. Scripts
    7.1. Filename
    7.2. Location
    7.3. Execution
    7.4. Head and Tail
    7.5. Comments
    7.6. Aliases and Bindings
    7.7. A Script
8. Version Information
9. Legal
    9.1. Copyright
    9.2. License
    9.3. Trademarks and Servicemarks
    9.4. Warranty Disclaimer

======================================================================
1. Introduction
======================================================================

This tutorial will try to explain all the details and procedures
necesarry for the creation of scripts and aliases.  Every aspect of
script making is explained in great detail.  Ample examples are
provided for each topic.  After reading this tutorial you will have a
complete understanding of aliases, console commands, and scripts.  You
will be able to create your own custom scripts from scratch and you
will understand other scripts just by looking at them.

The Quake engine is revolutionary in may ways to any previous game
engine, but one of the most useful advances is the availability of the
console.  The console allows the player to have direct influence on
the game engine by using commands to alter different aspects of the
engine.  These commands can be grouped together into aliases to
perform complex functions.  Just like commands can be grouped in
aliases, aliases can be grouped in scripts to produce an even larger
library of functions available to the player.  These functions might
be as complex as a script with many modules, each one containing
complex aliases to perform different functions, or as simple as a
single alias which sends text to other players.  The console allows
great freedom for the players to design and implement complex scripts
and aliases which will in turn enable them to use the game engine to
it's fullest potential and gain an edge over their enemy.  Just like
technology is used in modern warfare to gain an edge, aliases and
scripts are used in Quake.

======================================================================
2. Console
======================================================================

The console is the interface between the player and the Quake engine.
The player is allowed to enter and execute commands in the console
which in some form or another alter the functionality of the Quake
engine.  The console consists of two parts; the output display, and
the command line.  The display shows textual information about the
commands that have been executed or any information that the commands
show to the user.  The command line is a single empty line below the
display which serves as the place where the player enters commands or
information.  Basically, the player enters information on the command
line and sees the output on the display.

The access to the console is quite easy.  The default key to access
the console is the ~ (tilde) key located on the left of the 1 key.
There is also a command associated to that key which in turn pulls
down the console also, the command is toggleconsole.  When in a game,
this command will bring the console down when executed, and will pull
the console up when executed again.

======================================================================
3. Commands
======================================================================

The console accepts input in the form of commands which the user types
in.  The commands are the base of any type of script or alias.  There
is a very large number of commands which are available to the player
and each command performs a different action.  The lists of all
available commands for different implementations of the Quake engine
are available at the Documents section of this site.  These lists will
become very important to any script maker and everybody who is
interested in learning about scripts must become very familiar with
those documents.  I recommend that if you are unfamiliar with certain
commands which are shown in the examples in this tutorial, you should
look them up in the documents so that you may gain a complete
understanding of the examples.

There are so many different commands available to the Quake engine
that they had to be classified into seperate types by their syntax.
There are currently four different types of commands classified, which
cover all the current console commands.  It is very important to
understand each of the four types of commands and their functions.

----------------------------------------------------------------------
3.1 Action
----------------------------------------------------------------------

This type is very unique and very different from the other types in
it's own sense.  Commands of this type usually control the actions of
the player in the game.  These commands also have a very unique
characteristic, they have a command to turn the feature on and then to
turn it off.

An example of a function for one of these commands is the control of
the player's forward movement.  A command is executed that makes the
player move forward, this is the command +forward.  There is also a
counter-command which stops the player from moving forward, this is
the command -forward.  Another set of examples are the commands
+attack and -attack, which control if the player is firing the
currently selected weapon or not.  As you notice each action command
has a + (plus) and - (minus) part to it.  The + part initiates the
action and the - terminates the action.

As you see from the example above, the action commands have a very
simple syntax.  They just have an initiating part of the command which
is preceided by the + character, and a terminating part which is
preceided by the - character.  The default syntax looks something like
this "+action" or "-action".  Also action commands have no parameters.

----------------------------------------------------------------------
3.2 Command
----------------------------------------------------------------------

The name might be a little confusing right now but I think that this
is the best name to describe this type of commands.  These commands
are grouped together because they are left over from the other groups.
These commands are usually very different in usage and functionality
from the other command types.  Basically each command in this group
has it's own syntax.  Some of these commands have no parameters, some
have a number of parameters, and some take in parameters as numbers
and/or strings.  There really is not much that I can say about this
type of commands.

Sometimes the syntax "command" is available for commands which would
either initiate the command, or display the status of that command.
But sometimes the syntax is different for example "connect (IP
address:port)".  An example of use would be "connect
123.123.123.123:26999".

----------------------------------------------------------------------
3.3 Toggle
----------------------------------------------------------------------

This type of commands have a very strict rule for inclusion into the
group.  The commands in this group must take in a single numeric value
as the only parameter or take no value to report the current setting.
The value for the command must be a selection from a list of known
values.  Each value must define a seperate function or rule.

An example of a toggle is the deathmatch command.  There are three
different values available, from 0 to 2, for this command, and each
value defines different deathmatch rules.  Another example of a toggle
is the samelevel command which defines the rules for exiting the
level.  There are four different values available, from 0 to 3, and
each value defines different rules for exiting the level.  As you see,
both of these commands are toggles because they use a solitary
parameter which is a numeric value selected from a list of known
values.

The syntax for all toggle commands is similar and it is "command
(0|1)".  Usually toggle commands turn features on with the 1 parameter
and off with the 0 parameter.  Sometimes there are more features
available so higher values are used.  The syntax for the deathmatch
command is "deathmatch (0|1|2)".  An example of use would be
"deathmatch 1" or "deathmatch 2".

----------------------------------------------------------------------
3.4 Variable
----------------------------------------------------------------------

This type of commands is very similar to the toggles in one sense,
they only accept one parameter as a numerical value.  The only
difference between variables and toggles is that values used for
toggles are picked from a list of all known values, where values for
variables are not.  Variables have an analog quality to them in that
there are many different values available, where toggles have a more
digital quality where there is a limited number of values and each one
is clearly different from the next.

All variables share the same syntax which is "command (value)".  The
(value) represents a solitary numeric parameter.  And example of a
variable is the command cl_forwardspeed which controls the speed for
forward movement.  An example of use would be "cl_forwardspeed 50" or
"cl_forwardspeed 623".  Any value could be used as the parameter.
Also remember that variables have the ability to have the value as a
negative number, for example "cl_forwardspeed -100".

======================================================================
4. Syntax
======================================================================

The syntax for the console is very simple to understand and use.
There are only three special characters which are interpreted by the
console to perform special tasks.

----------------------------------------------------------------------
4.1 Space
----------------------------------------------------------------------

The first character is the space.  This character is used to seperate
commands from their parameters.  The examples below show the use of
the space.  This is a very basic character but should be noted
nontheless.

command 150
command 100 50 64 150

----------------------------------------------------------------------
4.2 Semicolon
----------------------------------------------------------------------

The second character is the ; (semicolor).  This character is used to
seperate commands on the same line.  The first example below is a
simple implementation.  This example will execute the first command
and then the second command.  The second example is more advanced and
will execute those commands in order.  So you see, if you want to use
more then one command on a line, just seperate them with a semicolon.

command;command
command;command 150;+command;command;-command;command 3

----------------------------------------------------------------------
4.3 Double-Quote
----------------------------------------------------------------------

The third character is the " (double-quote).  This character is used
to encapsulate multiple commands to serve as a single entity.  The
double-quotes are mostly used with the bind and alias commands and
sometimes with other commands to encapsulate their parameters.  The
use of the double-quotes is very basic and a little weird.  One thing
to remember is that double-quotes cannot be nested because the first
instance of the character initiates the encapsulation and the next
instance terminates it.  This is very important to remember and will
become useful with the introduction of bindings and aliases.

The first example shows the use of the double-quotes to encapsulate
the paramter which contains spaces.  The second example shows the
encapsulation of multiple commands which were seperated by the ;
(semicolon).  The third example shows the encapsulation of multiple
commands and the encapsulation of a command with it's parameter.

name "The Foo Master!"
alias foo "command;commmand;+command"
alias foo "command 7;+command;command"

The example below shows the illegal use of double-quotes for
encapsulation because of nesting.  This is the impropper use of the
double-quotes for encapsulation.  The end result of this example would
not work because the first double-quote opened the encapsulation, and
the next double-quote after the command name closed the encapsulation,
ignoring the rest of the command line.  This is very important to
remember.

alias foo "name "The Foo Master!";command;+command"

Basically, if you have a parameter which needs to have spaces or
semicolons inside then you encapsulate it with double-quotes.  When
you want a series of commands to be treated and executed as a single
command, you seperate each command with the semicolon and encapsulate
them with double-quotes.

----------------------------------------------------------------------
4.4 Double-Slash
----------------------------------------------------------------------

This pair of characters signify a comment.  It is usually found inside
script files where authors chose to leave comments on their work
inside the files.  Anything after the pair of characters is ignored as
a comment, execpt for the ; (semicolon) which terminates the comment.
It is not necessary to terminate comments with the semicolor, I just
included the information because it is possible.  I recommend that you
do not terminate comments with the semicolor.  I also recommend that
comments should appear on a seperate line which does not include any
commands.

Below is the correct use of comments, this is the recommened way and
should be used to make comments inside script files.

//The commands below initiate The Foo maneuver.

command;command;command

======================================================================
5. Bindings
======================================================================

This secion will deal with the bind command.  This command allows the
player to bind a command or a series of commands to a key or a button.
This is very useful for a number of reasons.  Because of this command,
you will be able to hit a key and have a single command executed or a
whole bunch of commands.  This command also allows the input devices
such as the keyboard and mouse to serve as an interface to the
console.

The first example is a very simple binding which will show the string
"Hi Foo!" to the player when the H key is pressed.  The second example
is a little more advanced example where multiple commands are used.
Every time the MOUSE1 button is pressed the player will jump, shoot
the gun, and display the message "Foo!" to the player.

bind h "echo Hi Foo!"
bind mouse1 "+attack;+jump;wait;-jump;-attack;echo Foo!"

Bindings also have a very special relationship with action commands.
When a key is bound to the + (plus) part of the action command that
key now has a new feature.  When the key is pressed the + (plus) part
of the action command is executed, as long as the key is held down
that action is in progress, when the key is released the - (minus)
part of the action is executed automatically.  This only works if the
+ (plus) part of the action command is the first command bound.  I
recommend that if you want to take advantage of this special feature,
you should only bind that command to the key and no other action
commands.

bind x +attack

You should be aware that Quake keeps all the binding information
inside the QUAKE\ID1\CONFIG.CFG file.  This file is automatically
generated by Quake with all he bindings that were set inside the game.
You are free to edit the bindings inside that file.  That file also
contains some commands which set some settings necessary for the
engine.

======================================================================
6. Aliases
======================================================================

This section will deal with the alias command.  This command is very
important because it allows the grouping of multiple commands into a
single command.  This grouping of commands serves many functions and
is the basis of scripts.  A lot of functions can be accomplished
through aliases and even the most complex of functions can be
accoplished with the use of multiple aliases.  Aliases impersonate
commands in every way, they can be nested within other aliases, they
can be bound, except that they cannot take parameters.

Aliases have a very simple syntax but are very powerful.  The syntax
for the alias command is 'alias (name) "(commands)"'.  The (name)
field stands for the name of the alias and the name servers as the
command to initiate that alias.  The (commands) field stands for the
commands that will be executed when the alias is called.  Now if you
want to initiate that alias you just have to type it's name foo in the
console.  You can also bind that alias name to a key.

alias foo "command;command;+command;command 231"

The first example is a very simple alias that when executed it will
broadcast the message "Hi foo!" to the other players on the server.
The second alias is a little more advanced because it aliases serveral
commands to serve as the Quick Axe function.

alias sayhi "say Hi foo!"
alias quickaxe "impulse 1;wait;+attack;wait;-attack"

Aliases can be nested very easily.  The example below shows that you
can create two seperate aliases and have them called from inside
another alias.

alias foo "foo1;foo2"
alias foo1 "echo foo one"
alias foo2 "echo foo two"

Aliases also have a very feature that they can immitate action
commands.  You can create an alias which will start with the + (plus)
character and will act like an action command.  Now you can bind a key
to that alias and when the key is pressed the + (plus) alias will be
executed, when it it released the - (minus) alias will be executed.
Also remember that you can and should make the - (minus) part of that
alias so that when you do not get an invalid command message.

alias +foo "+attack;+jump"
alias -foo "-attack;-jump"

The alias command also has a very useful feature.  When it is executed
without parameters it will show a list of all aliases that have been
created.  The alias command also has a shortcoming, you can only
create aliases, but you can never really destroy them.  You can make
an alias blank, but you can't remove it totally.

There is one very important thing that you should remember.  If you
create an alias with the same name as a command, that alias will not
work because all commands take precidence over aliases.

======================================================================
7. Scripts
======================================================================

Now that you have basic understanding of what you can do with aliases
and bindings it's time to learn about combining them into a whole
which is called the script.  Basically a script is a text file which
contrains aliases, bindings, and comments.  Most of the time scripts
are a single file, but sometimes they are composed of multiple files
because of size or design.

----------------------------------------------------------------------
7.1 Filename
----------------------------------------------------------------------

There are a couple of things that you should know about making a
script.  First, you want the filename of the script to have an
informative name or just use the nick name that you use to play Quake
as the filename for your script.  Next, use the extension .RC for all
your script files.  The reason for that extension is that it signifies
a script file in the Unix-like operating systems.  You might be
thinking why not use the extension .CFG, well the reason is that that
extension signifes configuration files.  The difference between
configuration files and scripts is that, configurations include
information necessary to set everything up such as the commands and
bindings, scripts on the other hand include aliases which are just
extra functions.  But you should also remember that you can make the
extension to your script files anything that you like, I just
recommend that you use the .RC extension because it has been used by
others and it has grown to signify scripts.  An example of a filename
of a script would be "foo.rc"

----------------------------------------------------------------------
7.2 Location
----------------------------------------------------------------------

When you create a script file you should place it somewhere below the
QUAKE\ID1 directory.  Do not place the script file in the QUAKE
directory because it will be inaccessible.  You can also place the the
script file in a special directory which was created for a Quake mod,
such as Threewave Capture the Flag.  In that case you can place a
script in the QUAKE\CTF directory, but you will only have access to
that script if you are currently playing that mod.

Most of the time you will create a single script file with all of you
favorite aliases and their respective bindings.  Although, if you are
really into scripts you might decide to split up your scripts into
multiple files.  I recommend that if you do make more the one file for
your scripts, you should create a seperate directory just for your
scripts.  I recommend that the directory be QUAKE\ID1\SCRIPTS, and you
would place all of your scripts there.  This will prevent clutter from
forming in the QUAKE\ID1 directory because of extra files.  This is
just my recommendation, you are free to put all of your script files
into the QUAKE\ID1 directory but you are risking mass clutter.

----------------------------------------------------------------------
7.3 Execution
----------------------------------------------------------------------

There are basically two ways of executing your script, manually or
automatically.  You could always execute your script manually with the
exec command, by doing exec foo.rc in the console.  Or you could have
your script executed automatically everytime Quake starts.  There is a
sepecial script file that Quake executes everytime that it starts, the
name of that file is autoexec.cfg.  The location of this script file
is QUAKE\ID1\AUTOEXEC.CFG.  This file might not exist on your system,
if it doesn't you are free to create it.  Now, if you want your script
file executed every time that Quake starts all you have to do is
create the autoexec.cfg file with the line "exec foo.rc" inside it.
If you have more than one script file and you have created the
QUAKE\ID1\SCRIPTS directory then you would create the autoexec.cfg
according to the example below.

exec scripts\foo1.rc
exec scripts\foo2.rc
exec scripts\foo3.rc

One thing that you should remember is that the autoexec.cfg file is a
regular script file.  You are free to place your aliases and their
respective bindings in that file.  I just recommened that you create a
script file seperate from the autoexec.cfg file and just have that
file execute your script.

----------------------------------------------------------------------
7.4 Head and Tail
----------------------------------------------------------------------

There are a couple more things that you should do when creating script
files.  These things are not vital nor even necessary to the creation
of scripts but should be done nontheless.  As the first two lines of
the script file you should make a comment with the name of the script
file and the author information.  It is also a good idea to include
information about how to contract the author such as email address.
The reason for this is that other people which might possibilly see
your script file and are intersted know what this file does and how to
contact the author.  Just as you include information at the beginning
of a script you should include a short line at the end of a script to
signify the end.  Since the information is presented to Quake in a
form of a comment it is ignored.

Just recently I have discovered a bug with Quake which I have never
experienced before since I always followed my own rules about
commenting the end of the script file with the End of File marker.  It
seems that when I was writing a test script which was missing the
marker the problem showed it's ugly head.  The problem is evident when
the game is started with the command line which might resemble
something like this "quake.exe +exec test.rc +command".  What will
happen is that the last line in the test.rc file will be joined up
with the command on the same line causing the last line never to
execute properly.  If the last line of the that file was
"command;command" the end result would be "command;commandcommand"
which would cause the error message 'Unknown Command
"commandcommand"'.  So, remember to put the tail on the file, or you
might experience problems.

Below is an example of the first two lines of a script file.

// The Foo Script
// Author: Foo Master (foomaster@foo.com)

Below is an example of the last line that should appear in your
script.  The acronym EOF stands for "End of File".

// EOF

----------------------------------------------------------------------
7.5 Comments
----------------------------------------------------------------------

It is possible to make extensive comments inside a script file to
describe the aliases, bindings, and uses.  I have to recommend against
putting in detailed information into script files as comments for a
number of reasons.  Script files should be as small as possible, all
detailed information should be provided in text files accompanying the
scripts.

Although large comments have no place inside script files, it is
appropriate and desirable to put a one line comment for each alias to
describe it's function, or a line comment to describe the general
function of a group of aliases.  I strongly recommend that in a large
script, aliases should have comments which name the alias.

Below is an example of an alias along with it's comment.

// Quick Hook

bind x +qh
alias +qh "impulse 22;+attack;echo Quick Hook"
alias -qh "-attack"

----------------------------------------------------------------------
7.6 Aliases and Bindings
----------------------------------------------------------------------

I recommend that when you create you script file, you should include
the binding for the alias inside your script file as opposed to it
being inside the config.cfg file.  The config.cfg file is usually
edited by Quake and that binding that you made might be removed by
Quake for some reason or another.  You should look at the example
above.

I recommend that you should create a neat structure inside your script
file so it becomes easy for you to navigate the file and find what you
need.  Usually, it is a good idea to keep aliases which serve one
function together in one bunch with the name of that function above
all the aliases.  If you have more aliases which serve different
functions, you should group aliases together by their functions and
name each function.

The example below shows two functions, each one having more than one
alias.  Each function is named by a comment.

----------------------------------------------------------------------
7.7 A Script
----------------------------------------------------------------------

Below is an example of what a script file should look like.  The
starting and ending comments for the script are present and they name
the script and provide author information.  There are multiple aliases
which serve different functions, each function is seperated from the
other functions, and each function is named throught a comment.

// The Foo Script
// Author: Foo Master (foomaster@foo.com)

// Quick Hook

bind z +qh
alias +qh "impulse 22;+attack;echo Quick Hook"
alias -qh "-attack"

// Rocket Jump

bind x +rj
alias +rj "cl_pitchspeed 100000;impulse 7;+lookdown;wait;-
lookdown;cl_pitchspeed 150;+jump;+attack;echo Rocket Jump"
alias -rj "-attack;-jump;force_centerview"

// Zoom

bind c +zoom
alias +zoom "fov 22;m_pitch 0.005;m_yaw 0.005"
alias -zoom "fov 90;m_pitch 0.022;m_yaw 0.022"

// EOF

======================================================================
8. Version Information
======================================================================

----------------------------------------------------------------------
May 18, 2000
----------------------------------------------------------------------

* Updated the legal and licensing terms of this document and it is now
  released under the Free Software Foundation's GNU Free Documentation
  License, Version 1.1.

* Removed the links to the Cascading Style Sheet file which was
  providing the stylistic markup for this document in order to solve
  an existing major problem with troublesome web serving software and
  to promote better accessibility and availability of this document
  for the future at the price of removing the coloring and formatting
  markup from this document.

* Changed the format of my email address from URL format to a
  proprietary format in order to defeat the automatic gathering of my
  email address by web crawler software and to prevent the
  increasingly annoying barrage of unsolicited commercial
  advertisements that I have been receiving.

* Removed all other HTML LINK tags to prevent future problems with web
  serving software.

* Renamed the Index section to Table Of Contents to correct this long
  lasting mistake.

----------------------------------------------------------------------
November 6, 1998
----------------------------------------------------------------------

* New legal terms for this document.  It is now released under the
  Free Software Foundation's GNU General Public License Version 2.

----------------------------------------------------------------------
September 29, 1998
----------------------------------------------------------------------

* Updated the HTML markup in the document.  This should be the last
  such update because I think I solved all of the previous problems
  with HTML and the correct display of this document.

* Added my email address to the Abstract section.  It was been removed
  long time ago because of too many emails, and I hope that this isn't
  the case this time.

* Updated the HTML 4.0 deceleration to include the URI of the DTD, as
  stated in the standard.

* Added the MIME Content-Type and Content-Language fields to
  explicitly set the character set encoding and language information.

* Added HTML meta information to each document to include all
  necessary header information to help search engines.

* Changed the Modified: field to Last Modified:, and Location: to
  Source: to avoid ambiguity.

* Changed the usage of bold and italic stylistic markup in order to
  facilitate better display of this document in browsers which do not
  support Cascading Style Sheets.

----------------------------------------------------------------------
July 20, 1998
----------------------------------------------------------------------

* I have removed my email address from this document because I was
  getting unwanted emails.  If you want to contact me, go to my web
  site.

----------------------------------------------------------------------
July 16, 1998
----------------------------------------------------------------------

* Changed the internal HTML style for indentations and also to space
  out the fields for easier reading.

* Added subsection 9.4. Trademarks in the 9. Legal section to take
  care of any trademark legalities.

* Added a copyright notice to the Abstract section along with a short
  description about this document.

----------------------------------------------------------------------
March 13, 1998
----------------------------------------------------------------------

* Made some formatting changes.

----------------------------------------------------------------------
May 2, 1997
----------------------------------------------------------------------

* First release.

======================================================================
9. Legal
======================================================================

----------------------------------------------------------------------
9.1. Copyright
----------------------------------------------------------------------

This work is copyrighted pseudonymously by the author under all
applicable laws.  The author reserves all rights to this work.  The
copyright statement for this work is "Copyright (C) 1997-2000
JakFrost, All Rights Reserved".

----------------------------------------------------------------------
9.2. License
----------------------------------------------------------------------

Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with no
Invariant Sections, no Front-Cover Texts and no Back-Cover Texts.  You
can access the license at http://www.gnu.org/copyleft/fdl.html or you
can write to the Free Software Foundation, Inc., 59 Temple Place,
Suite 330, Boston, MA 02111-1307, USA to request a copy.  Please
preserve all authorship and contact information when distributing or
modifying this work.  All derivative works or works containing parts
of this work must be released under the same license or a later
version of it.

----------------------------------------------------------------------
9.3. Trademarks and Servicemarks
----------------------------------------------------------------------

All trademarks and servicemarks used in this work are acknowledged and
are the property of their rightful owners.

----------------------------------------------------------------------
9.4. Warranty Disclaimer
----------------------------------------------------------------------

THIS WORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY; WITHOUT EVEN THE
IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
PURPOSE.  THE AUTHOR IS NOT LIABLE FOR ANY RESULTS ARRISING FROM THE
USE OF THIS WORK.  ALL RISKS AND RESULTS THEREOF FALL ON THE USER.

Copyright (C) 1997-2000 JakFrost, All Rights Reserved


