diff options
| author | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
|---|---|---|
| committer | Felix Morgner <felix.morgner@gmail.com> | 2026-08-24 11:16:07 +0200 |
| commit | c068f22329d5cc722622a2183bbb22eef2093df7 (patch) | |
| tree | 12d56c1aede67988a55e241364606bfbb4dba933 /docs | |
| download | openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.tar.xz openparsec-c068f22329d5cc722622a2183bbb22eef2093df7.zip | |
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/makeodt_readme.txt | 374 | ||||
| -rwxr-xr-x | docs/todo.txt | 174 | ||||
| -rw-r--r-- | docs/tutorial.txt | 790 |
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( ®com, 0, sizeof( user_command_s ) ); + + // register "starmap" command + regcom.command = "starmap"; + regcom.numparams = 0; + regcom.execute = Cmd_STARMAP; + regcom.statedump = NULL; + CON_RegisterUserCommand( ®com ); +} + +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> + |
