aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
committerFelix Morgner <felix.morgner@gmail.com>2026-08-24 11:16:07 +0200
commitc068f22329d5cc722622a2183bbb22eef2093df7 (patch)
tree12d56c1aede67988a55e241364606bfbb4dba933 /docs
downloadopenparsec-main.tar.xz
openparsec-main.zip
initial importHEADmain
Diffstat (limited to 'docs')
-rw-r--r--docs/makeodt_readme.txt374
-rwxr-xr-xdocs/todo.txt174
-rw-r--r--docs/tutorial.txt790
3 files changed, 1338 insertions, 0 deletions
diff --git a/docs/makeodt_readme.txt b/docs/makeodt_readme.txt
new file mode 100644
index 0000000..bbc5cf4
--- /dev/null
+++ b/docs/makeodt_readme.txt
@@ -0,0 +1,374 @@
+
+------------------------------------------------------------------------------
+makeodt: The Parsec 3d Model Utility
+------------------------------------------------------------------------------
+mailto:parsec@parsec.org http://www.parsec.org/
+------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+1. INTRODUCTION
+------------------------------------------------------------------------------
+
+This distribution is geared towards an artistic/technical audience that wants
+to design their own spacecraft and other 3d objects and import them in Parsec.
+
+It contains the utility we are using for converting 3d models into the binary
+object format Parsec uses (.od2). The tool is called makeodt, since the
+original format was called .odt ("object data format"), but by now Parsec
+mostly uses its second incarnation, consequently called .od2 (and the
+supplied version of makeodt exclusively generates .od2 files).
+
+Please bear in mind right from the start that designing, converting, and
+importing your own 3d models into Parsec is by no means an easy task.
+
+There are quite some shortcomings and tricky parts to the conversion process,
+and especially on the front end side we could have done a lot better. For
+exactly this reason, we are not only providing binaries for Win32, Linux,
+and MacOS X, but also the complete source code (licensed under the LGPL,
+see below). If you would like to have additional input formats, provide
+more object information, build a graphical front end, or anything else you
+find wanting, please, by all means, feel free to go ahead and plug it right
+in.
+
+Actually, makeodt is an extremely tiny front end to a quite powerful library
+called BspLib, that we have developed some time ago. The main purpose of this
+library was compilation of BSP trees, but this functionality is not exported
+by makeodt, since the current Parsec models do not employ BSP trees at all.
+If you have a look at the BspLib source and ask yourself why it is that
+large, well, it's able to do a lot more than just convert objects, and it
+also contains quite some legacy stuff (especially with regard to input file
+formats).
+
+The primary input format that makeodt is able to read is VRML V1.0, so the
+main requirement for building your own models is that you are somehow able to
+export your mesh in this format. Next, your textures have to be in either
+.tga, .jpg, or .3df format, since makeodt needs to read the dimensions of your
+textures during model conversion, and it knows only these image file formats.
+
+As soon as you have converted your model into an .od2 file, you will have to
+write a Parsec console script for loading it within the game. Especially for
+spacecraft (with the corresponding locations for firing missiles, lasers,
+and the like) this is not a task accomplished in a mere five minutes.
+
+Finally, for redistribution, you should package all the data (the model
+itself, the textures, and the console script) for your model(s) into a single
+file, which you can easily give to your friends and make available on the net.
+
+
+------------------------------------------------------------------------------
+2. LICENSE
+------------------------------------------------------------------------------
+
+The license for the BspLib and makeodt sources is the GNU LGPL, see the
+included files called COPYING.
+
+QvLib, the VRML 1.0 parsing library by Paul S. Strauss of SGI, which
+BspLib is using in order to read VRML1 files, can be used, modified,
+and distributed freely. The included version has been modified slightly.
+The original version can be found at
+ftp://ftp.sgi.com/sgi/inventor/2.0/qv1.0.tar.Z
+for instance.
+
+
+------------------------------------------------------------------------------
+3. MODEL CONVERSION OVERVIEW
+------------------------------------------------------------------------------
+
+To plunge right in, these are the nine steps we usually run through in order
+to get a model (a 3d object) into Parsec:
+
+1. design the model in some external editor
+2. export it in VRML V1.0 format, or convert an exported format into VRML1
+3. put the .wrl file together with all textures in a single directory
+4. fix the bugs the VRML exporter has put in (your mileage may vary ;)
+5. invoke makeodt in this directory (this generates the .od2 file)
+6. copy the textures and the .od2 file into a single directory
+7. either turn this directory into a package or copy it into the parsec dir
+8. write the console script for loading the model, textures, and shaders
+9. execute the loading script in the parsec console (usually automatically)
+
+As you can see, makeodt is only part of the whole process (namely, step 5).
+Everything else is concerned with design, file management, and putting
+together additional information (in the console script).
+
+If you want to distribute your model, or have everything nice and tidy after
+you have finalized it, you put all the corresponding files in a single
+package, see section 7 below.
+
+
+------------------------------------------------------------------------------
+4. COMMAND LINE OPTIONS
+------------------------------------------------------------------------------
+
+makeodt itself only takes two input parameters, the name of the file you want
+to convert, and an optional scale factor:
+
+1. input file specification: "-i <filename_no_wrl_extension>"
+2. scale factor specification: "-s <float>"
+
+We determine the exact scale factor we want to use for each model by trial
+and error.
+
+makeodt requires all textures to be in the same directory as the .wrl file,
+in either .tga, .jpg, or .3df format, and generates a corresponding .od2 file.
+Parsec itself is also able to read textures from these three image file
+formats.
+
+
+------------------------------------------------------------------------------
+5. LOADING A MODEL IN PARSEC
+------------------------------------------------------------------------------
+
+Loading a model in Parsec (from a console script) is usually done in the
+following order:
+
+ 1. load all textures. they must be available before the actual model gets
+ loaded. if they are not, the model won't load.
+
+ 2. load the model (the actual object). this might actually consist of
+ loading several objects (one for each level of detail), together with
+ specifying switching thresholds in terms of viewing distance.
+
+ 3. define all shaders (if any). this allows to create texture and color
+ animations, specify transparency, etc.
+
+ 4. attach the shaders to the respective parts of the model.
+
+If the model is a spacecraft, the following steps also apply:
+
+ 5. designate the model as a spacecraft, so players will actually be able to
+ select it in the spacecraft viewer. this also allows to specify a texture
+ for the little image appearing in the monitors on the upper left and
+ right corners of the cockpit.
+
+ 6. specify a description text for the spacecraft, that will be displayed in
+ the spacecraft viewer.
+
+ 7. specify properties like maximum damage, number of missiles the ship can
+ carry, and so on; but also purely geometric properties that are not
+ contained in the model, like the positions where lasers and missiles
+ should appear when fired.
+
+We will elaborate a bit on each of these steps and illustrate the
+corresponding console commands by using examples:
+
+ 1. "load texture texname file texname.tga"
+ this will load a texture called "texname" from a file called
+ "texname.tga". these two names are completely unrelated, within the
+ engine only the former matters.
+
+ 2. "load object firebird file firebird.od2"
+ this will load an object class called "firebird" from a file called
+ "firebird.od2". these two names are completely unrelated, within the
+ engine only the former matters.
+
+ "load object test file (t0.od2 t1.od2) lodmag (110) lodmin (160)"
+ this will load an object class called "test" containing two levels
+ of detail from the files "t0.od2" and "t1.od2". the switching thresholds
+ are distances and are specified as a hysteresis. i.e., magnification
+ should occur closer (smaller value) to the viewer than minification
+ (larger value). this avoids nervous toggling at a certain fixed viewing
+ distance.
+
+ 3. "shader.def ex_energy_tube shader (iter_texrgb iter_alphablend)"
+ shaders are beings of their own, please see chapter 11 in the
+ parsec thesis distribution for a discussion.
+
+ 4. "shader.set class (test) lod -2 shader test_hull texture test"
+ same as 3.
+
+For further examples, please refer to the included example console scripts.
+
+
+------------------------------------------------------------------------------
+6. MODEL SHADERS
+------------------------------------------------------------------------------
+
+Shaders are mostly important for animated objects. Simple objects, and static
+spacecraft do not necessarily need them.
+
+Please refer to chapter 11 (Shaders) and chapter 14 (The Command Console) in
+the parsec thesis distribution for a detailed discussion (see section 10
+below for download location).
+
+
+------------------------------------------------------------------------------
+7. BUILDING AND REGISTERING A DATA PACKAGE
+------------------------------------------------------------------------------
+
+In order to avoid clobbering your Parsec directory (and everybody else's)
+with dozens or even hundreds of small files, we strongly suggest packaging
+all your stuff into Parsec packages, similar to the original distribution.
+
+A Parsec package is simply a collection of files stored in a single file
+with a simple header tacked onto it. The package creator/extractor is part
+of the Parsec executable itself.
+
+In order to extract the files contained in a Parsec package (pscdata0.dat,
+pscdata2.dat, or pscdata3.dat, for instance) you invoke the Parsec executable
+with the following command line parameters:
+
+-getpack --pack <packname> --list <listname>
+
+This will extract <packname> into the current directory and also store a
+list of the extracted files in <listname>. The "--list" option is actually
+optional, but it's handy to have this list available, especially if you
+want to repackage the extracted files, for which you will need just such
+a list.
+
+In order to create a package you invoke Parsec with these parameters:
+
+-makepack --pack <packname> --list <listname>
+
+which creates the package <packname> by packaging all the files listed in
+<listname> into it (they won't be compressed, just put into a single file,
+just like a .tar package, although in a different binary format).
+
+When dealing with packages, you always have to keep in mind that the file
+names of the packaged files must not be longer than fifteen characters.
+In the future we will probably lift this legacy restriction, but for the
+time being, keep your file names short.
+
+When you have packaged your files, you of course want to be able to have
+Parsec load files from it. This won't happen automatically, but there are
+multiple (and not too complicated) ways for registering your new package
+with Parsec. The method you actually use usually depends on whether you
+are testing your package, or whether you want to read data from a finalized
+package (which probably also means a person other than you wants to do this).
+
+First, you can list all already registered packages in the command console
+by using the "listdata packages" command. When Parsec is already running
+you can add additional packages to this list by using the
+"package register <packname>" command. Be sure to include the extension.
+
+You can also register packages on startup with the --pack command line
+option.
+
+However, both of these methods won't automatically load anything, because
+no console scripts get executed when the package is registered. The package
+and all the files it contains are simply added to the search path.
+
+In order to do this, you have to register a package as a mod. What happens
+when you do this is that a console script called "boot.con" will automatically
+be executed for you, provided that you include such a script in your package.
+
+When your register a mod (using either the --mod, or the --modforce command
+line option, see below), you actually register a directory. This directory
+must then contain a .dat file with the same name (excluding the extension)
+as the directory/mod name itself.
+
+For example, say you want to register a mod simply containing an additional
+ship called "darkwing", you do this:
+
+1. create darkwing.dat containing a boot.con script, the .od2 file (which
+ need not be called darkwing.od2, the only "special" name is boot.con),
+ and all the textures and maybe additional scripts for loading the ship.
+
+2. put darkwing.dat in a darkwing subdir (making it darkwing/darkwing.dat)
+
+3. start Parsec with --mod darkwing
+
+Of course, boot.con has to invoke the console script loading The Darkwing.
+(It's good practice not to put a lot into boot.con itself, but to simply
+delegate to other scripts.) Or any additional number of ships, for that
+matter.
+
+Now for the difference between the --mod and --modforce options. For the
+time being, --mod is what you usually want to use, because it adds the
+mod packages _after_ the official Parsec packages. In contrast to this,
+the --modforce option bypasses these packages entirely, which means your
+mod package(s) have to provide _all_ the data in Parsec (or your own
+totally modified version of it), for that matter.
+
+As long as they are data-only mods (which, currently, all mods are), you can
+register multiple mods by simply using multiple --mod options on the same
+command line, like:
+
+--mod darkwing --mod evilrazor
+
+or whatever.
+
+
+------------------------------------------------------------------------------
+8. THE ART OF DESIGNING A PARSEC MODEL
+------------------------------------------------------------------------------
+
+Now that we have at least briefly covered the technical aspects of importing
+a model into Parsec, there are lots of additional issues involved. We will
+try to mention some of them here.
+
+First, textures are costly. Both in terms of memory and in terms of state
+switches during rendering. If the latter doesn't strike a bell, just let it
+suffice that the fewer different textures an object uses, the better.
+From five to ten textures per spacecraft, and just one or two for a
+power-up should do the trick.
+
+Also, all textures have to be a power of two in width and height, e.g.,
+256x128, 128x32, and so on.
+
+The older Parsec models are all using a maximum texture resolution of 256x256
+which is a good compromise between memory consumption and quality. However,
+all the original artwork was done in four times the in-game resolution in
+order to prepare for hardware that is able to handle larger textures.
+
+Indeed, with the advent of texture compression, textures up to 1024 along one
+dimension have become feasible. So by now the latest ships of Parsec are
+able to use the original artwork.
+
+Second, the Parsec engine is not a high polygon count engine. It supports
+a lot of different (graphics hardware) platforms and has been developed over
+several years, which means the number of polygons you can push through a
+state-of-the-art graphics card don't mean all that much to it.
+
+Which is to say: use as few polygons as possible, a couple hundred should be
+enough for one spacecraft (say, up to 600).
+
+Finally, we would like to recommend browsing through all the existing Parsec
+artwork (especially the pscdata2.dat and pscdata3.dat packages) to have
+a reference how we are using all this. Especially the syntax and usage of
+console commands can be best gleaned from there, since we haven't covered all
+of them in this short document.
+
+If you want to learn how to use shaders, the _powups.con console script is
+the best place to start. The scripts for loading spacecraft are called
+_f1_2.con, _f2_2.con, and so on.
+
+
+------------------------------------------------------------------------------
+9. INTERNAL STRUCTURE
+------------------------------------------------------------------------------
+
+For those of you desiring to use the source, here are a couple of words about
+its structure.
+
+First, the core of makeodt is the BspLib, which resides in tool_src/BspLib.
+It's a C++ class library that is utilized by makeodt. If you're interested
+in BspLib itself, there is still a web page describing some of its innards
+(http://www.cg.tuwien.ac.at/~msh/bsplib/). In case you are wondering, this
+source has nothing to do with the Parsec source itself whatsoever. So, you
+don't have to have a look at it if you want to work on the Parsec source.
+future. Parsec deals with objects, geometry, and the like in an entirely
+different way.
+
+Second, for parsing VRML V1.0 files we use a very slightly modified version
+of QvLib, a public domain library for parsing such files, which was publicly
+released by SGI quite some time ago. It resides in tool_src/QvLib.
+
+Third, there are two files of the actual Parsec source, which the BspLib
+needs in order to be able to save Parsec object files. These are od_geomv.h
+and od_odt.h which can be found in game_src/common/include.
+
+Last, but not least, there are a couple of files in tool_src/makeodt which
+glues all of the above together in a very simple command line tool.
+
+
+------------------------------------------------------------------------------
+10. RESOURCES
+------------------------------------------------------------------------------
+
+The primary source for more in-depth Parsec information is the Parsec
+thesis ("Design and Architecture of a Portable and Extensible Multiplayer
+3D Game Engine"), which is available for download from the Parsec download
+page (http://www.parsec.org/download.html "PARSEC SDK DOWNLOADS").
+
diff --git a/docs/todo.txt b/docs/todo.txt
new file mode 100755
index 0000000..a4f81cd
--- /dev/null
+++ b/docs/todo.txt
@@ -0,0 +1,174 @@
+
+------------------------------------------------------------------------------
+PARSEC OPEN SOURCE TODO LIST
+------------------------------------------------------------------------------
+mailto:parsec@parsec.org http://www.parsec.org/
+------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+1. INTRODUCTION
+------------------------------------------------------------------------------
+
+To help in coordinating the Parsec open-source effort, this document
+describes the most important tasks that need to be done in order to improve
+the initial open-source Parsec release, and to create a truly enjoyable
+gaming experience.
+
+
+------------------------------------------------------------------------------
+2. TASKS FOR PROGRAMMERS
+------------------------------------------------------------------------------
+
+Interested programmers that want to help improve the Parsec code-base, should
+pick tasks from this list first, to avoid a lack of focus and direction.
+Please communicate with the other developers on the openparsec-devel mailing
+list, if you decide to take on one of these tasks.
+
+* Improve client/server code
+ - redesign remote event interface
+ - position interpolation between state snapshots of ships
+ - exact laser positions according to time-delta to clients packet sendtime
+ - stargate jumps must be initiated by the server
+ - finish new clientside prediction model
+ - determine which packets need to be send reliable
+ - priorities for E_Distributables if exceeding bandwidth
+ - first version should work with laser weapons only
+ - get powerups to work completely
+ - plausibility checks of player movements
+ - add rocket weapon support
+ - after laser and rocket weapons work, get particle weapons to work
+ - collision detection ship/ship must be done on the server
+ - better collision response on ship/ship collisions
+ - teleporters
+ - packet/state compression when exceeding bandwidth constraints
+ - get emp weapon to work
+ - implement new serverside sim
+
+* Player stats and federation handling
+ - handover player stats when doing stargate-jumps inside of federation
+ ( gameserver to gameserver communication )
+ - introduce unique playerid
+
+* Client/MacOS X: fix vertex-array rendering failure ( e.g.: teleporter,
+ vaportrail, emp )
+
+* Server: split BOOT_SV.CON into several console scripts
+
+* Server: console code should load data from the packages ( PSCDATA0.DAT )
+
+* split E_REList in E_REList and G_REListWriter. the latter contains all
+ gamecode specific functions
+
+* Win32: introduce precompiled headers to speedup compile times
+
+* Linux/Client: check segfault when connecting to gameserver
+
+* Linux/Client: check segfault in XQueryExtension()
+
+* Win32/Server: check the memory leak we get in the server
+
+* Win32/Server: check crash in CURSES.DLL when running from the IDE
+
+* consolidate and check packetsize constants ( e.g.NET_MAX_DATA_LENGTH,
+ NET_UDP_DATA_LENGHT, CurMaxDataLength, NET_ALLOC_DATA_LENGTH,
+ RECORD_PACKET_SIZE )
+
+* Client: check whether the demo recording for PEER still works ( GMSV
+ does not have demo recording for now )
+
+* time entries in UTL_LOGFILE should also give the correct date/time
+
+* integrate old ( DEBUG.CPP ) and new ( UTL_MEMORYMANAGER.CPP ) memory
+ management. we need C++ equivalents for ALLOCMEM/FREEMEM for NEW/DELETE
+
+* Server: get rid of the proxy variable access in CON_INT_SV.
+ directly modify the members of the global classes ( set/get functions )
+
+* Server: autocompletion does not work in the console
+
+* Add bots
+ Preliminary bot interface is available. ( GM_BOT_CL.CPP )
+ Server-side vs. client-side bots?
+ Integration with networking code?
+
+* Improve starmap
+ Add more features, fix the existing problems.
+
+* Improve planet code (clipping, culling, rendering, collision detection)
+ Preliminary planet code with ring system support is available. Needs work
+ in several areas. Needs changes in REND, needs LOD support.
+ Needs proper integration with server (see starmap spawning code in server).
+
+* Add proper visibility detection code for particle flares. Current method
+ uses Z-Buffer reads, which is incredibly slow on some drivers/GPUs (e.g.
+ ATI drivers on OS X) or not working at all (Matrox drivers?).
+ Use ray-casting as an alternative method.
+
+ -or-
+
+ Revamp ship propulsion effects completely, using more sophisticated iter
+ drawing, and textures. Let go of particle effects?
+
+* Add other objects that can exist in space (e.g. asteroid fields)
+ Implementation should be done using custom objects.
+
+* Rewrite AUD subsystem
+ using FMOD or OpenAL it should be possible to use the same codebase on all
+ platforms (-> licensing issues?)
+
+* Add new music playback system. MP3 support is not available in open-source
+ version. Add Ogg Vorbis support (-> interdependencies with AUD subsystem)
+
+* Revamp VID subsystem to allow various additional resolutions (wide-screen)
+ and improve FOV handling, and view parameters for projection (vid_supp.c)
+ Make this more flexible. Avoid the need for code changes to support new
+ resolutions.
+
+* Add HID Manager joystick support for Mac OS X.
+
+* Add audio CD support for Mac OS X (-> coordinate with AUD subsystem rewrite)
+
+* Fix bugs in X11 that occur at startup when trying to grab the mouse cursor.
+
+* Add Carbon Events support in Mac OS X version.
+
+* Bring NULL subsystems up-to-date.
+
+* Fix and improve launcher application on Win32 and Linux.
+
+* Write a GUI frontend to allow placing of objects in world, e.g. stargates,
+ teleporters, asteroid fields, etc.
+
+* Enhance and improve tool chain. Add additional input object file formats
+ to makeodt/BspLib. Automate process, add a GUI frontend.
+
+* Implement a real scripting language for console scripts.
+ Evaluate existing solutions (Python, JavaScript, etc.). Probably needs a
+ big revamp of the console code, and lots of interfacing with game objects.
+ Huge task!
+
+* Implement big font support in Glide.
+ Need to tile texture in 256x256 pixel chunks, draw using Glide primitives
+ (iter code that is in place doesn't seem to work?).
+
+
+
+------------------------------------------------------------------------------
+3. TASKS FOR ARTISTS
+------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+4. TASKS FOR OTHER INDIVIDUALS
+------------------------------------------------------------------------------
+
+* Write generic game documentation
+
+* Provide end-user support
+ Write and maintain the FAQ, answer e-mail requests, update the news section
+ of the webpage.
+
+* Basically take over tasks that are currently handled by the developers.
+
+*
diff --git a/docs/tutorial.txt b/docs/tutorial.txt
new file mode 100644
index 0000000..a75d120
--- /dev/null
+++ b/docs/tutorial.txt
@@ -0,0 +1,790 @@
+
+------------------------------------------------------------------------------
+PARSEC DEVELOPER TUTORIAL V1.0
+------------------------------------------------------------------------------
+mailto:parsec@parsec.org http://www.parsec.org/
+------------------------------------------------------------------------------
+
+
+------------------------------------------------------------------------------
+1. INTRODUCTION
+------------------------------------------------------------------------------
+
+This document is supposed to give you a quick start with the Parsec source
+code. Of course this can only be an incomplete guide, a full documentation
+has yet to be written, please keep this in mind while reading this tutorial.
+
+We'll cover some of the more easy modifications of Parsec, such as
+changing/adding new graphics, 3D objects, samples and console commands.
+
+Some of these modifications can be done without changing source code, and
+some require you to change the source code and recompile the Parsec
+executable.
+
+Conventions used in this document:
+
+ * Commands that have to be issued on the command-line, are written like
+ this:
+
+ > program -option1 -option2
+
+ * Commands that have to be issued on Parsec's console, are written like
+ this:
+
+ ::command option1 option2
+
+ NOTE: Parsec's command console can be opened using the tilde key (~).
+
+
+------------------------------------------------------------------------------
+2. EXTRACTING THE DATA PACKAGES
+------------------------------------------------------------------------------
+
+All the data files used by Parsec are stored in the package files called
+pscdata0.dat, pscdata2.dat and pscdata3.dat (pscdata1.dat only contains the
+splashscreen image).
+To change/view the data files, you need to extract the package files. This
+can be achieved using the packaging tools that are built right into the
+Parsec executable.
+
+Start Parsec with the following command line option to extract all the
+data files from a package (pscdata2.dat in this example):
+
+ > parsec -getpack --pack pscdata2.dat --list pscdata2.lst
+
+To view the contents of a package file use.
+
+ > parsec -getpack --pack pscdata2.dat --view
+
+To extract a single file from the package use:
+
+ > parsec -getpack --pack pscdata2.dat --file <filename>
+
+If you want to rebuild the package file with new data files, you need
+to edit the .lst file and rebuild the package using:
+
+ > parsec -makepack --pack pscdata2.dat --list pscdata2.lst
+
+NOTE:
+Be careful not to put .mp3 files into pscdata0.dat, as they will be
+converted to .wav files at startup, increasing the size of pscdata0.dat
+significantly!
+
+
+------------------------------------------------------------------------------
+3. ADDING/CHANGING GRAPHICS
+------------------------------------------------------------------------------
+
+This section explains how to change/add graphics in Parsec.
+Nearly all graphics in Parsec are textures, drawn on triangles or polygons
+using the rendering or drawing subsystems, even the 2D graphics found in
+the menu or the spacecraft viewer.
+All textures are loaded by the 'load' console command, so to change
+Parsec's graphics, all you need to do is write a little console script
+issuing multiple 'load' commands.
+For testing purposes, you can issue the 'load' command directly on the
+console. This will cause your new texture to show up immediately.
+Textures in Parsec usually come in one of the following three image file
+formats:
+
+ (*) .3df (Glide texture format by 3dfx)
+ (*) .tga (Targa)
+ (*) .jpg (JPEG)
+
+3DF files can contain pre-calculated mipmaps and textures in various formats
+(both with and without alpha channel), but are limited to 16 bit per pixel
+color depth.
+TGA files can contain 32 bit per pixel data (that is 24 bits for color and
+an 8 bit alpha channel), but usually only offer a cheap RLE compression.
+JPG files are usually very small, so they're are very well suited for high
+resolution textures, in full 24 bit color. However, they don't support an
+alpha channel.
+
+So before you can add your new textures to the game, you need to convert them
+into one of the supported texture file formats. Your image editor of choice
+will most likely be able to save JPG and TGA.
+For creating .3df files, there are tools available for various platforms.
+We recommend Texus by 3dfx (part of the Glide SDK, source code is included,
+which can be compiled on nearly every platform),
+or AsinDes (for Windows only).
+
+Here's a step-by-step guide for creating a new texture as a .3df file:
+(if you choose to use .jpg or .tga files, you can skip points (2) and (3))
+
+ (1) Draw a texture in your graphics program of choice, e.g.
+ Photoshop or Gimp. Ensure that the dimensions of your texture are
+ powers of 2, and not larger than 256. Valid texture sizes are 128x64,
+ 256x256, 256x128, 64x32, 64x64 and so on.
+ If your texture size does not conform to this standard, it will not
+ show up if the Glide rendering subsystem is used, or performance on
+ OpenGL cards might suffer.
+
+ (2) Save your texture in a format that your .3df converter is able to
+ read. We recommend .tga. Be sure to include an alpha channel if your
+ texture is supposed to have transparent areas.
+
+ (3) Convert the texture to a -3df file.
+ Using the command-line version of Texus, this might look like this:
+
+ > texus -mn -R 128 128 -t argb4444 -o texture.3df texture.tga
+
+ This converts a 128x128 .tga image into a .3df texture including the
+ alpha channel without generating mipmaps. This is a suitable way to
+ convert textures for use in the menu or the cockpit.
+
+ If you want to convert textures for use on a 3D object, you should
+ include mipmaps by removing the -mn option.
+
+ If your texture has many similiar colors (e.g. lots of brown, or lots
+ of grey), you might get better results by using the ap88 color format
+ instead of argb4444. If your texture does not have an alpha channel,
+ you should use the rgb565 command with the -t parameter.
+
+ (4) Copy the texture in the same directory that the Parsec executable
+ resides in.
+
+ (5) Start up Parsec and enter the console by pressing the tilde key.
+
+ (6) Type the command:
+
+ ::listdata textures
+
+ (8) Browse through the texture list, until you've found the texture you
+ want to replace. Unless you know the filename of the texture you want to
+ replace, this might require some trial and error.
+ You can also locate the correct texture by looking in one of the .con
+ files that are used to load the textures, for example _cockpit.con.
+ Remember the name of the texture, which is printed in parantheses.
+
+ (9) Ensure that the AUX_ENABLE_TEXTURE_OVERLOADING flag is set, by typing
+
+ ::AUX_ENABLE_TEXTURE_OVERLOADING 1
+
+ on the console.
+
+ (10) Replace the texture by overloading it with the newly created one,
+ using the load command:
+
+ ::load texture (texturename) file texture.3df
+
+ where texturename is the name you remembered from the texture list
+ in step (8).
+ The parantheses are only required if the texture name contains
+ space characters.
+
+Please note that the new texture doesn't necessarily need to have the same
+width/height as the original texture. If your new texture has a different
+size, it will be scaled automatically.
+
+Some textures you might want to try to change are:
+
+(scv00.3df) - the spacecraft viewer background (256x256 tiles
+(scv01.3df) starting at the top left corner)
+(scv02.3df)
+(scv10.3df)
+(scv11.3df)
+(scv12.3df)
+
+(loganiXX) - the logo animation in the bottom right corner of the menu
+ (30 frames)
+
+(sg_int.3df) - the water-like surface inside a stargate
+
+(corner1) - the little decorations at the corners of translucent panels
+(corner2)
+(corner3)
+(corner4)
+
+(helix001) - the helix cannon particle texture
+
+Get the correct dimensions of those textures from the texture list, and
+create new ones with the same size.
+
+You can use texus or some other .3df convertor to convert the .3df
+textures back to the graphics format of your choice to edit them in your
+favourite graphics program.
+
+If you want to keep your new graphics, you need to make sure they are
+loaded when Parsec starts up. To do this, you should write a .con console
+script containing the 'load' commands and add the name of the script to
+the sys_dat.con file. This is necessary to ensure that the texture data is
+correctly converted when switching video subsystems.
+
+It's important that you're familiar with the methods used to create and load
+textures in Parsec, because this is part of creating new ship models.
+
+
+------------------------------------------------------------------------------
+4. ADDING/CHANGING A 3D OBJECT
+------------------------------------------------------------------------------
+
+To modify 3D objects in Parsec, you take a simliar route as with changing
+textures, so you also need to be familiar with that technique. Be sure
+to read the previous section, and make sure you understood everything
+there, because you'll need it when dealing with objects.
+
+Parsec uses its own flexible 3D object file format, called ODT, or the
+newer revision OD2. In general, you'll only need to deal with .od2 files.
+These files are usually created by our own tool called "makeodt".
+Please consult the document on makeodt, to learn how to use it.
+Makeodt is able to import VRML files (.wrl extension), and convert these
+along with all the necessary texture information into .od2 files. It does
+NOT read VRML2 (VRML97) files!
+
+Once you have an .od2 file you can load this just like a texture, using
+the load command.
+
+load object (firebird) file fighter1.od2
+
+Here's a step-by-step guide for creating a new ship for Parsec:
+
+ (1) Use a good 3D modelling program (e.g. 3D Studio Max) to create your
+ model. Paint some textures for the model, and use UV mapping to map
+ them onto your ship.
+
+ (2) Save your model as a VRML file (.wrl), and your textures as Targa
+ files (.tga). Use the procedures described in the previous chapter to
+ convert the textures to .3df or alternatively .jpg files.
+
+ (3) Use makeodt to convert your ship into a .od2 file.
+
+ (5) Take a look at mon_f1.3df and recreate a similiar texture showing
+ your ship, using your 3D rendering program. This texture will be
+ displayed in the cockpit monitors on the top of the screen.
+
+ (6) Make a copy of _f1_2.con (from pscdata2.dat) and edit it. You need to
+ change the load texture commands to load the textures of your ship,
+ replace every occurence of firebird with your new ship's name, change
+ the ship description and adapt the weapon outlet positions to suit your
+ model.
+
+ (7) Load your edited .con file and you should be able to select your new
+ ship in the spacecraft viewer.
+
+If you followed these steps, your ship will be fully functional, but it
+won't have any propulsion effects yet. Take a look at the more modern scripts,
+e.g. _f8_2.con, to find out how to define the particle position for the
+propulsion effects (commands are called "classpart" and "classiter").
+
+If you just want to convert a simple object for a weapon effect or similar,
+you can skip steps (5) and (6), as these are specific to ships.
+
+Please consult the makeodt documentation for a more thorough discussion of
+console script commands for loading objects, specifying shaders, etc.
+
+
+------------------------------------------------------------------------------
+5. ADDING/CHANGING A SAMPLE
+------------------------------------------------------------------------------
+
+Replacing one of Parsec's soundeffects is just as simple as changing a
+texture, maybe even simpler.
+Using the listdata command you can get a list of all currently loaded
+samples.
+
+::listdata samples
+
+Pick one that you want to replace, and create a .wav file for it,
+using your favourite sample editor.
+Now open _sound.con and change the line corresponding to the sample that
+you want to replace. You can also specify a new volume.
+Reload _sound.con on the console or restart Parsec to test the new sample.
+
+
+------------------------------------------------------------------------------
+6. ADDING A CONSOLE COMMAND
+------------------------------------------------------------------------------
+
+Parsec's console contains a large number of available commands, most of which
+are defined within the console modules (source files named con_*).
+Console commands that are specific to a part of the game are usually defined
+within the modules responsible for the implementation of that part (e.g.
+commands related to the network code are implemented in the net_* source files
+directly). These commands (usually called user commands) are registered from
+the REGISTER_MODULE function, which is called automatically upon program
+startup.
+
+The registration of a user command might look like this:
+
+// module registration function -----------------------------------------------
+//
+REGISTER_MODULE( STARMAP )
+{
+ user_command_s regcom;
+ memset( &regcom, 0, sizeof( user_command_s ) );
+
+ // register "starmap" command
+ regcom.command = "starmap";
+ regcom.numparams = 0;
+ regcom.execute = Cmd_STARMAP;
+ regcom.statedump = NULL;
+ CON_RegisterUserCommand( &regcom );
+}
+
+The user_command_s structure contains necessary parameters that describe the
+user command, and a function pointer to the actual implementation of the
+command.
+A string containing the parameters of the command will be passed to the
+implementation function.
+Here's an example of a the above "starmap" command, which is very simple, as
+it doesn't require any parameters. It just calls the internal function
+MAP_ActivateStarmap() to activate the starmap.
+
+// console command to activate/deactivate the starmap -------------------------
+//
+PRIVATE
+int Cmd_STARMAP( char *paramstr )
+{
+ ASSERT( paramstr != NULL );
+ HANDLE_COMMAND_DOMAIN_SEP( paramstr );
+
+ MAP_ActivateStarmap();
+
+ return TRUE;
+}
+
+For more complex console commands, it's necessary to parse the parameter
+string.
+There are helper functions available which make this task a lot easier (and
+less error prone) if the parameters have a key/value pair structure.
+
+You start by defining a table of the keys that you want to be able to parse:
+
+// key table for net.master command -------------------------------------------
+//
+key_value_s net_master_key_value[] = {
+
+ { "num", NULL, KEYVALFLAG_NONE },
+ { "addr", NULL, KEYVALFLAG_NONE },
+
+ { NULL, NULL, KEYVALFLAG_NONE },
+};
+
+Possible KEYVALFLAG values are:
+KEYVALFLAG_NONE -> no specific options for this key
+KEYVALFLAG_DISALLOW -> if this key exists, an error will be returned
+KEYVALFLAG_IGNORE -> ignore this key and its value.
+KEYVALFLAG_MANDATORY -> if this key is missing, an error will be returned
+KEYVALFLAG_PARENTHESIZE -> the value of this key might be enclosed by (), which
+ is used for value strings that contain whitespace.
+
+Of course these flags can be combined if necessary, e.g:
+KEYVALFLAG_MANDATORY | KEYVALFLAG_PARENTHESIZE
+to specify a key that is both mandatory and uses a string value that
+contains a space character, for example.
+
+enum {
+
+ KEY_NET_MASTER_NUM,
+ KEY_MET_MASTER_ADDR,
+};
+
+The enum declarations are used to allow easier access to the entries of the
+key table.
+
+In your command implementation function, you then call:
+
+ // scan out all values to keys
+ if ( !ScanKeyValuePairs( net_master_key_value, paramstr ) ) {
+ return TRUE;
+ }
+
+This will automatically parse the parameter string into key/value pairs.
+If the parameter string does not conform to the constraints specified in
+the key table (e.g. mandatory keys are missing), FALSE will be returned,
+and an error will be output on the console automatically.
+
+If the parsing was sucessful, the key table will be populated with the
+values for each key, in the value field of the key_value_s structure.
+If the value field is NULL, this means that the key was optional and
+has not been found. So make sure the check against NULL, before using
+the value.
+
+Additional helper functions are available to convert the value field
+(which is still a string) to its integer or float representation:
+
+ // get masterserver number
+ int num = 0;
+ if ( ScanKeyValueInt( &net_master_key_value[ KEY_NET_MASTER_NUM ], &num ) < 0 ) {
+ CON_AddLine( invalid_arg );
+ return TRUE;
+ }
+
+This will retrieve the value string for the "num" key, as defined in the
+key table, and convert the string to an integer, which will be stored in
+the num variable.
+Other functions that can be used here include:
+ScanKeyValueIntList(), ScanKeyValueFloat(), ScanKeyValueFloatList(), etc.
+
+If your command parameter parsing becomes more complex, it is highly
+recommended that you include a syntax definition in Backus-Naur Form as a
+comment in the source code.
+You can see examples of this with nearly every console command implementation
+in Parsec. You can also find a list of all syntax definitions at the end of
+this document.
+
+------------------------------------------------------------------------------
+APPENDIX A: CONSOLE COMMAND SYNTAX DEFINITIONS
+------------------------------------------------------------------------------
+
+In this section you can find syntax definitions of some of the common
+Parsec console commands in Backus-Naur Form (BNF).
+Please note that this list does not include the vast amount of integer
+commands. These don't require a special syntax, and can be shown by using
+the 'listintcommands' command.
+Parameters in brackets are optional, the | character is used to denote a
+logical or condition.
+
+
+ bkgn_add_command ::= 'bkgn.add' <itemspec>
+ itemspec ::= <samplespec> | <trackspec> |
+ samplespec ::= 'sample' <paranthesized name of sample>
+ trackspec ::= 'track' <trackno>
+ streamspec ::= 'stream' <filename>
+ silencespec ::= 'silence' <seconds>
+
+
+ bkgn_remove_command ::= 'bkgn.remove' <itemspec>
+ itemspec ::= <idspec> | <samplespec> | <trackspec>
+ idspec ::= 'id' <id of item>
+ samplespec ::= 'sample' <paranthesized name of sample>
+ trackspec ::= 'track' <trackno>
+
+
+ bkgn_list_command ::= 'bkgn.list'
+
+
+ bkgn_group_command ::= 'bkgn.group' <itemspec>
+ itemspec ::= 'item' <id of item>
+
+
+ aud_volume_command ::= 'aud.volume' [<volume>]
+
+
+ aud_samplevolume_command ::= 'aud.samplevolume' <samplename> [<volume>]
+
+
+ aud_playsample_command ::= 'aud.playsample' <samplespec>
+ samplespec ::= <samplename> | <sampleid>
+ samplename ::= 'name' <name of sample>
+ sampleid ::= 'id' <id of sample>
+
+
+ play_command ::= 'play' <demo_name>
+ demo_name ::= "valid script name"
+
+
+ level_load_command ::= 'level.load' levelname_spec
+ levelname_spec ::= <string>
+
+
+ level_save_command ::= 'level.save' levelname_spec
+ levelname_spec ::= <string>
+
+
+ level_info_command ::= 'level.info'
+
+
+ swaying_command ::= 'gfx.swaying' [<period_spec>] [<ampl_spec>] [<phase_spec>]
+ period_spec ::= '(' <int> <int> ')'
+ ampl_spec ::= '(' <int> <int> ')'
+ phase_spec ::= <int>
+
+
+ crosstarget_command ::= 'crosstarget'
+
+
+ scale_command ::= 'cockpit.scale' [<factor>]
+
+
+ weaponreg_command ::= 'weaponreg' <slot_spec> [<icon_avail_spec>]
+ slot_spec ::= 'slot' <slotnum>
+ icon_avail_spec ::= 'icon_avail' <texturename> | <texture_list>
+ icon_unavail_spec ::= 'icon_unavail' <texturename>
+ picture_spec ::= 'pic' <texturename> | <texture_list>
+ texture_list ::= '(' <texturename>+ ')'
+
+
+ quicksay_command ::= 'quicksay'
+
+
+ range_command ::= 'radar.range' [<range>]
+
+
+ shipdesc_command ::= 'shipdesc' <class_spec> [<text_spec>]
+ class_spec ::= 'class' <classname> | 'id' <classid>
+ text_spec ::= 'text' <textline>
+ caption_spec ::= 'caption' <captiontext>
+ clear_spec ::= 'clear' ['caption'|'text']
+
+
+ emp_conf_command ::= 'emp.conf' [<lifetime_spec>] [<maxwidth_spec>]
+ lifetime_spec ::= 'lifetime' <int>
+ maxwidth_spec ::= 'maxwidth' <float>
+ lambda_spec ::= 'lambda' <float>
+ fadeout_spec ::= 'fadeout' <int>
+ waves_spec ::= 'waves' <int>
+ delay_spec ::= 'delay' <int>
+ energy_spec ::= 'energy' <int>
+
+
+ emp_conf_command ::= 'empup1.conf' [<lifetime_spec>] [<maxwidth_spec>]
+ lifetime_spec ::= 'lifetime' <int>
+ maxwidth_spec ::= 'maxwidth' <float>
+ lambda_spec ::= 'lambda' <float>
+ fadeout_spec ::= 'fadeout' <int>
+ waves_spec ::= 'waves' <int>
+ delay_spec ::= 'delay' <int>
+ energy_spec ::= 'energy' <int>
+
+
+ emp_conf_command ::= 'empup2.conf' [<lifetime_spec>] [<maxwidth_spec>]
+ lifetime_spec ::= 'lifetime' <int>
+ maxwidth_spec ::= 'maxwidth' <float>
+ lambda_spec ::= 'lambda' <float>
+ fadeout_spec ::= 'fadeout' <int>
+ waves_spec ::= 'waves' <int>
+ delay_spec ::= 'delay' <int>
+ energy_spec ::= 'energy' <int>
+ emp_command ::= 'emp'
+
+ shockwave_command ::= 'shockwave' [<lifetime_spec>] [<maxwidth_spec>]
+ lifetime_spec ::= 'lifetime' <int>
+ maxwidth_spec ::= 'maxwidth' <float>
+ lambda_spec ::= 'lambda' <float>
+ fadeout_spec ::= 'fadeout' <int>
+
+
+ inp_weaponsel_command ::= 'inp.weaponsel' <number>
+
+
+ inp_cycleguns_command ::= 'inp.cycleguns'
+
+
+ inp_cyclemissiles_command ::= 'inp.cyclemissiles'
+
+
+ inp_cycletargets_command ::= 'inp.cycletargets'
+
+
+ inp_zerospeed_command ::= 'inp.cycletargets'
+
+
+ inp_targetspeed_command ::= 'inp.targetspeed'
+
+
+ inp_cyclepanel_command ::= 'inp.cyclepanel' <number>
+
+
+ clientrate_command ::= 'net.clientrate' [<frequency>]
+
+
+ serverrate_command ::= 'net.serverrate' [<frequency>]
+
+
+ jump_command ::= 'jump' <server>
+ server ::= valid hostname or IP address of gameserver
+
+
+ net_master_command ::= 'net.master' <num_spec> [<addr_spec>]
+ num_spec ::= 'num' <int>
+ addr_spec ::= 'addr' valid hostname or IP address of masterserver
+
+
+ serverlist_request_command ::= 'serverlist.request' [<max_ping>] [<min_players>]
+ max_ping ::= 'ping' <int>
+ min_players ::= 'players' <int>
+
+
+ serverlist_show_command ::= 'serverlist.show'
+
+
+ srvcmd_command ::= 'srvcmd' <command_spec>
+ command_spec ::= <valid server control command>
+
+
+ colanim_command ::= 'colanim' <name> <coltab0> [<coltab1>] [<mode-spec>]
+ name ::= "may be parenthesized to include whitespace"
+ coltab0 ::= 'src' <coltab-src> 'len' <coltab-len>
+ coltab1 ::= 'src2' <coltab-src> 'len2' <coltab-len>
+ coltab_src ::= '(' <tab-spec> | <wave-spec> ')'
+ coltab_len ::= <int>
+ mode_spec ::= 'mode' 'add' | 'mul'
+ tab_spec ::= 'tab' <col-list> [<comp>] [<mask>] [<t-equi> | <t-list>]
+ col_list ::= '(' <int>+ ')'
+ comp ::= 'comp' '1' | '3' | '4'
+ t_equi ::= 't' <int>
+ t_list ::= 'tl' '(' <int>+ ')'
+ wave_spec ::= 'wave' <wave-name> [<t-equi>] [<max>] [<min>] [<mask>]
+ wave_name ::= 'tri' | 'saw' | 'ramp' | 'sine'
+ max ::= 'max' <int>
+ min ::= 'min' <int>
+ mask ::= 'mask' ['r'] ['g'] ['b'] ['a']
+
+
+ net_config ::= 'net.subsys' [[<protocol>] <packet_api>]
+ protocol ::= 'peer-to-peer' | 'slot-server' | 'game-server'
+ packet_api ::= 'ipx' | 'udp'
+
+
+ audio_config ::= 'aud.conf' [conf_spec] [conf_spec]
+ conf_spec ::= 'off' | 'music' | 'sfx'
+
+
+ input_config ::= 'inp.conf' [conf_spec] [conf_spec]
+ conf_spec ::= 'off' | 'joystick' | 'mouse'
+
+
+ classiter_command ::= 'classiter' <class_spec> ( [<command>] [<trafo>] ) |
+ class_spec ::= 'class' <classname> | 'id' <classid>
+ command ::= 'cmd' 'reset'
+ trafo ::= 'trafo' '(' <vertex_spec> [<float>] ')'
+ apex_info ::= 'apex' '(' <float> [<float> [<float>]] ')'
+ prim_type ::= 'prim' 'tri' | 'quad' | 'pent'
+ vertex_list ::= 'vtxs' '(' <vertex_spec>+ ')'
+ vertex_spec ::= <float> <float> <float>
+
+
+ classpart_command ::= 'classpart' <class_spec> ( [<command>] [<trafo>] ) |
+ class_spec ::= 'class' <classname> | 'id' <classid>
+ command ::= 'cmd' 'reset'
+ trafo ::= 'trafo' '(' <vertex_spec> [<float>] ')'
+ pdef ::= 'pdef' <pdef_name>
+ position ::= 'pos' '(' <vertex_spec> ')'
+ size ::= 'size' <float>
+ render_mode ::= 'render' 'poslight' | 'thrust' | 'missile'
+ vertex_spec ::= <float> <float> <float>
+
+
+ faceinfo_command ::= 'faceinfo' <class-spec> <face-spec>
+ class_spec ::= <class-name> | <class-id>
+ class_name ::= 'class' <name>
+ class_id ::= 'classid' <int>
+ face_spec ::= <face-id-spec> | <attrib-spec>
+ face_id_spec ::= 'faceid' <face-id>
+ attrib_spec ::= <shader-spec> | <tex-spec>
+ shader_spec ::= 'shader' <shader-iter> | <shader-name>
+ shader_iter ::= '(' 'iter_xx'* 'flag_xx'* ')'
+ shader_name ::= "valid name of shader"
+ tex_spec ::= 'texture' <texture-name>
+
+
+ key_command ::= 'key' ( <key_spec> <command> | <func_spec> <mkc_code> )
+ key_spec ::= 'akc_*'
+ command ::= "arbitrary string, may contain whitespace"
+ func_spec ::= 'func_*' | 'func_1_*' | 'func_2_*'
+ mkc_code ::= 'mkc_*' | '0x' <hex-digit> <hex-digit> | <nil>
+ hex-digit ::= [0-9a-f]
+ nil ::= "if no mkc_code is supplied mapping will be deassigned."
+
+
+ bind_command ::= 'bind' ( <key_spec> <command> | <func_spec> <mkc_code> )
+ key_spec ::= 'akc_*'
+ command ::= "arbitrary string, may contain whitespace"
+ func_spec ::= 'func_*' | 'func_1_*' | 'func_2_*'
+ mkc_code ::= 'mkc_*' | '0x' <hex-digit> <hex-digit> | <nil>
+ hex-digit ::= [0-9a-f]
+ nil ::= "if no mkc_code is supplied mapping will be deassigned."
+
+
+ load_command ::= 'load' <data_type> <name> [<key> <value>]*
+ data_type ::= 'object' | 'texture' | 'texfont' | 'bitmap' | 'sample'
+ name ::= "may be parenthesized () to include whitespace"
+ key ::= "valid keys depend on data type"
+
+
+ defshader_command ::= 'shader.def' <shader-name> [<shader-spec>] [<color>] [<anims>]
+ shader_name ::= "may be parenthesized to include whitespace"
+ shader_spec ::= 'shader' <shader-iter> | <shader-name>
+ shader_iter ::= '(' 'iter_xx'* 'flag_xx'* ')'
+ shader_name ::= "valid name of shader"
+ color ::= 'color' '(' <int> <int> <int> [<int>] ')'
+ anims ::= [<texanim>] [<colanim> [<colanim-mode>]]
+ texanim ::= 'texanim' "valid name of texanim"
+ colanim ::= 'colanim' "valid name of colanim"
+ colanim_mode ::= 'colmode' 'add' | 'mul' | 'nobase'
+
+
+ setshader_command ::= 'shader.set' <class-spec> <shader-spec> [<face-spec>]
+ class_spec ::= <class-name> | <class-id> [<lod-spec>]
+ class_name ::= 'class' <name>
+ class_id ::= 'id' <int>
+ lod_spec ::= 'lod' <int>
+ shader_spec ::= 'shader' <shader-iter> | <shader-name>
+ shader_iter ::= '(' 'iter_xx'* 'flag_xx'* ')'
+ shader_name ::= "valid name of shader"
+ face_spec ::= <tex-spec> | <face-id-spec>
+ tex_spec ::= 'texture' <texture-name>
+ face_id_spec ::= 'faceid' <face-id> | <face-id-list>
+ face_id_list ::= '(' <face-id>+ ')'
+
+
+ texanim_command ::= 'texanim' <name>
+ name ::= "may be parenthesized to include whitespace"
+
+
+ summon_command ::= 'summon' <object_spec> [<init_spec>] [<multi_spec>]
+ object_spec ::= <classname_spec> | <classid_spec> | <sfx_spec> | <vtype_spec>
+ classname_spec ::= 'class' <classname>
+ classid_spec ::= 'id' <classid>
+ sfx_spec ::= 'sfx' <sfxname>
+ vtype_spec ::= 'vtype' <typename>
+ init_spec ::= [<origin_spec> [<space_spec>]] [<speed_spec>] [<frame_spec>]
+ origin_spec ::= 'origin' '(' <float> <float> <float> ')'
+ space_spec ::= 'space' 'vv' | 'vw' | 'wv' | 'ww'
+ speed_spec ::= 'speed' <int>
+ frame_spec ::= 'frame' '(' <float> <float> <float> <float> <float> <float> <float> <float> <float> ')'
+ multi_spec ::= [<count_spec> [<repl_spec>] [<space_spec>]]
+ repl_spec ::= <offset_spec> | <scatter_spec>
+ count_spec ::= 'count' <int>
+ offset_spec ::= 'offs' '(' <float> <float> <float> ')'
+ scatter_spec ::= 'scatter' '(' <float> <float> <float> ')'
+ classname ::= "may be parenthesized () to include whitespace"
+ classid ::= <int>
+ sfxname ::= 'energyfield'
+
+
+ do_creg_command ::= 'do_creg' [<int_list>]
+ int_list ::= <int> [<int_list>]
+
+
+ shipclass_command ::= 'shipclass' <class_spec> [<monitor_texture_spec>]
+ class_spec ::= 'class' <classname> | 'id' <classid>
+ monitor_texture_spec ::= 'texture' <texturename>
+
+
+ extraclass_command ::= 'extraclass' <class_spec>
+ class_spec ::= 'class' <classname> | 'id' <classid>
+
+
+ decoy_command ::= 'decoy'
+
+
+ cloak_command ::= 'cloak'
+
+
+ pdef_command ::= 'pdef' <name> <texanispec> [<xfoanispec>]
+ name ::= "may be parenthesized () to include whitespace"
+ texanispec ::= <basename> <tablen> [<basedig>] [<textab>] [<textabctrl>]
+ basename ::= 'base' <name>
+ tablen ::= 'len' <int>
+ basedig ::= 'dig' '1' | '2' | '3' | '4'
+ textab ::= 'tab' '(' <texframespec> <textimespec> ')'
+ texframespec ::= ( ['base' <int>] ['stride' <int>] ) | ['frm' '(' <intlist> ')']
+ textimespec ::= ['t' <int>] | ['tl' '(' <intlist> ')']
+ textabctrl ::= ['bgn' <int>] ['rep' <int>] ['end' <int>]
+ xfoanispec ::= 'xfolen' <int> ['xfotab' <xfotab>] [<xfotabctrl>]
+ xfotab ::= '(' ')'
+ xfotabctrl ::= ['xfobgn' <int>] ['xforep' <int>] ['xfoend' <int>]
+ intlist ::= [<intlist>] <int>
+
+
+ pattach_command ::= 'pattach' <pdefname> <shipspec> <origin> [<ref_z>] [<type>]
+ shipspec ::= 'ship' 'local' | 'target'
+ origin ::= 'origin' '(' <float> <float> <float> ')'
+ ref_z ::= 'size' <float>
+ type ::= 'normal' | 'flare' | 'light'
+
+
+ inp_weaponsel_command ::= 'inp.weaponsel' <number>
+