home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #6 / amigaacscoverdisc1998-061998.iso / games / descent / source / main / bmread.c < prev    next >
Text File  |  1998-06-08  |  60KB  |  2,000 lines

  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
  12. */
  13. /*
  14.  * $Source: f:/miner/source/main/rcs/bmread.c $
  15.  * $Revision: 2.4 $
  16.  * $Author: john $
  17.  * $Date: 1995/03/28 18:05:29 $
  18.  * 
  19.  * Routines to parse bitmaps.tbl
  20.  * 
  21.  * $Log: bmread.c $
  22.  * Revision 2.4  1995/03/28  18:05:29  john
  23.  * Fixed it so you don't have to delete pig after changing bitmaps.tbl
  24.  * 
  25.  * Revision 2.3  1995/03/07  16:52:03  john
  26.  * Fixed robots not moving without edtiro bug.
  27.  * 
  28.  * Revision 2.2  1995/03/06  16:10:20  mike
  29.  * Fix compile errors if building without editor.
  30.  * 
  31.  * Revision 2.1  1995/03/02  14:55:40  john
  32.  * Fixed bug with EDITOR never defined.
  33.  * 
  34.  * Revision 2.0  1995/02/27  11:33:10  john
  35.  * New version 2.0, which has no anonymous unions, builds with
  36.  * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
  37.  * 
  38.  * Revision 1.1  1995/02/25  14:02:36  john
  39.  * Initial revision
  40.  * 
  41.  * 
  42.  */
  43.  
  44.  
  45. #pragma off (unreferenced)
  46. static char rcsid[] = "$Id: bmread.c 2.4 1995/03/28 18:05:29 john Exp $";
  47. #pragma on (unreferenced)
  48.  
  49. #include "settings.h"
  50.  
  51. #ifdef EDITOR
  52.  
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <stdarg.h>
  56. #include <conio.h>
  57. #include <string.h>
  58. #include <io.h>
  59.  
  60. #include "types.h"
  61. #include "inferno.h"
  62. #include "gr.h"
  63. #include "bm.h"
  64. #include "mem.h"
  65. #include "cflib.h"
  66. #include "mono.h"
  67. #include "error.h"
  68. #include "object.h"
  69. #include "vclip.h"
  70. #include "effects.h"
  71. #include "polyobj.h"
  72. #include "wall.h"
  73. #include "textures.h"
  74. #include "game.h"
  75. #include "multi.h"
  76.  
  77. #include "iff.h"
  78. #include "cfile.h"
  79.  
  80. #include "hostage.h"
  81. #include "powerup.h"
  82. #include "laser.h"
  83. #include "sounds.h"
  84. #include "piggy.h"
  85. #include "aistruct.h"
  86. #include "robot.h"
  87. #include "weapon.h"
  88. #include "gauges.h"
  89. #include "player.h"
  90. #include "fuelcen.h"
  91. #include "endlevel.h"
  92. #include "cntrlcen.h"
  93. #include "compbit.h"
  94. #include "args.h"
  95.  
  96.  
  97. #include "editor\texpage.h"
  98.  
  99. #define BM_NONE            -1
  100. #define BM_COCKPIT         0
  101. #define BM_TEXTURES         2
  102. #define BM_UNUSED              3
  103. #define BM_VCLIP              4
  104. #define BM_EFFECTS        5
  105. #define BM_ECLIP               6
  106. #define BM_WEAPON             7
  107. #define BM_DEMO              8
  108. #define BM_ROBOTEX        9
  109. #define BM_WALL_ANIMS    12
  110. #define BM_WCLIP             13
  111. #define BM_ROBOT            14
  112. #define BM_GAUGES            20
  113.  
  114. #define MAX_BITMAPS_PER_BRUSH 30
  115.  
  116. extern player_ship only_player_ship;        // In bm.c
  117.  
  118. static short        N_ObjBitmaps=0;
  119. static short        N_ObjBitmapPtrs=0;
  120. static int            Num_robot_ais = 0;
  121. int    TmapList[MAX_TEXTURES];
  122. char    Powerup_names[MAX_POWERUP_TYPES][POWERUP_NAME_LENGTH];
  123. char    Robot_names[MAX_ROBOT_TYPES][ROBOT_NAME_LENGTH];
  124.  
  125. //---------------- Internal variables ---------------------------
  126. static int             Registered_only = 0;        //    Gets set by ! in column 1.
  127. static int            SuperX = -1;
  128. static int            Installed=0;
  129. static char         *arg;
  130. static short         tmap_count = 0;
  131. static short         texture_count = 0;
  132. static short         clip_count = 0;
  133. static short         clip_num;
  134. static short         sound_num;
  135. static short         frames;
  136. static float         time;
  137. static int            hit_sound = -1;
  138. static byte         bm_flag = BM_NONE;
  139. static int             abm_flag = 0;
  140. static int             rod_flag = 0;
  141. static short        wall_open_sound, wall_close_sound,wall_explodes,wall_blastable, wall_hidden;
  142. float        vlighting=0;
  143. static int            obj_eclip;
  144. static char         *dest_bm;        //clip number to play when destroyed
  145. static int            dest_vclip;        //what vclip to play when exploding
  146. static int            dest_eclip;        //what eclip to play when exploding
  147. static fix            dest_size;        //3d size of explosion
  148. static int            crit_clip;        //clip number to play when destroyed
  149. static int            crit_flag;        //flag if this is a destroyed eclip
  150. static int            tmap1_flag;        //flag if this is used as tmap_num (not tmap_num2)
  151. static int            num_sounds=0;
  152.  
  153.  
  154.  
  155. //------------------- Useful macros and variables ---------------
  156. #define REMOVE_EOL(s)        remove_char((s),'\n')
  157. #define REMOVE_COMMENTS(s)    remove_char((s),';')
  158. #define REMOVE_DOTS(s)      remove_char((s),'.')
  159.  
  160. #define IFTOK(str) if (!strcmp(arg, str))
  161. char *space = { " \t" };    
  162. //--unused-- char *equal = { "=" };
  163. char *equal_space = { " \t=" };
  164.  
  165. void remove_char( char * s, char c )
  166. {
  167.     char *p;
  168.     p = strchr(s,c);
  169.     if (p) *p = '\0';
  170. }
  171.  
  172. //---------------------------------------------------------------
  173. int compute_average_pixel(grs_bitmap *new)
  174. {
  175.     int    row, column, color;
  176.     char    *pptr;
  177.     int    total_red, total_green, total_blue;
  178.  
  179.     pptr = new->bm_data;
  180.  
  181.     total_red = 0;
  182.     total_green = 0;
  183.     total_blue = 0;
  184.  
  185.     for (row=0; row<new->bm_h; row++)
  186.         for (column=0; column<new->bm_w; column++) {
  187.             color = *pptr++;
  188.             total_red += gr_palette[color*3];
  189.             total_green += gr_palette[color*3+1];
  190.             total_blue += gr_palette[color*3+2];
  191.         }
  192.  
  193.     total_red /= (new->bm_h * new->bm_w);
  194.     total_green /= (new->bm_h * new->bm_w);
  195.     total_blue /= (new->bm_h * new->bm_w);
  196.  
  197.     return BM_XRGB(total_red/2, total_green/2, total_blue/2);
  198. }
  199.  
  200. //---------------------------------------------------------------
  201. // Loads a bitmap from either the piggy file, a r64 file, or a
  202. // whatever extension is passed.
  203.  
  204. bitmap_index bm_load_sub( char * filename )
  205. {
  206.     bitmap_index bitmap_num;
  207.     grs_bitmap * new;
  208.     ubyte newpal[256*3];
  209.     int iff_error;        //reference parm to avoid warning message
  210.     char fname[20];
  211.  
  212.     bitmap_num.index = 0;
  213.  
  214. #ifdef SHAREWARE
  215.     if (Registered_only) {
  216.         //mprintf( 0, "Skipping registered-only bitmap '%s'\n", filename );
  217.         return bitmap_num;
  218.     }
  219. #endif
  220.  
  221.     _splitpath(  filename, NULL, NULL, fname, NULL );
  222.  
  223.     bitmap_num=piggy_find_bitmap( fname );
  224.     if (bitmap_num.index)    {
  225.         //mprintf(( 0, "Found bitmap '%s' in pig!\n", fname ));
  226.         return bitmap_num;
  227.     }
  228.  
  229.     //MALLOC( new, grs_bitmap, 1 );//hack KRB
  230.     new = (grs_bitmap *)malloc(1*sizeof(grs_bitmap));
  231.     iff_error = iff_read_bitmap(filename,new,BM_LINEAR,newpal);
  232.     new->bm_selector=0;
  233.     if (iff_error != IFF_NO_ERROR)        {
  234.         mprintf((1, "File %s - IFF error: %s",filename,iff_errormsg(iff_error)));
  235.         Error("File %s - IFF error: %s",filename,iff_errormsg(iff_error));
  236.     }
  237.  
  238.     if ( iff_has_transparency )
  239.         gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
  240.     else
  241.         gr_remap_bitmap_good( new, newpal, -1, SuperX );
  242.  
  243.     new->avg_color = compute_average_pixel(new);
  244.  
  245.     mprintf( (0, "N" ));
  246.     bitmap_num = piggy_register_bitmap( new, fname, 0 );
  247.     free( new );
  248.     return bitmap_num;
  249. }
  250.  
  251. void ab_load( char * filename, bitmap_index bmp[], int *nframes )
  252. {
  253.     grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
  254.     bitmap_index bi;
  255.     int i;
  256.     int iff_error;        //reference parm to avoid warning message
  257.     ubyte newpal[768];
  258.     char fname[20];
  259.     char tempname[20];
  260.  
  261. #ifdef SHAREWARE
  262.     if (Registered_only) {
  263.         Assert( bogus_bitmap_initialized != 0 );
  264.         mprintf(( 0, "Skipping registered-only animation '%s'\n", filename ));
  265.         bmp[0] = &bogus_bitmap;
  266.         *nframes = 1;
  267.         return;
  268.     }
  269. #endif
  270.  
  271.  
  272.     _splitpath( filename, NULL, NULL, fname, NULL );
  273.     
  274.     for (i=0; i<MAX_BITMAPS_PER_BRUSH; i++ )    {
  275.         sprintf( tempname, "%s#%d", fname, i );
  276.         bi = piggy_find_bitmap( tempname );
  277.         if ( !bi.index )    
  278.             break;
  279.         bmp[i] = bi;
  280.         //mprintf(( 0, "Found animation frame %d, %s, in piggy file\n", i, tempname ));
  281.     }
  282.  
  283.     if (i) {
  284.         *nframes = i;
  285.         return;
  286.     }
  287.  
  288.     iff_error = iff_read_animbrush(filename,bm,MAX_BITMAPS_PER_BRUSH,nframes,&newpal);
  289.     if (iff_error != IFF_NO_ERROR)    {
  290.         mprintf((1,"File %s - IFF error: %s",filename,iff_errormsg(iff_error)));
  291.         Error("File %s - IFF error: %s",filename,iff_errormsg(iff_error));
  292.     }
  293.  
  294.     for (i=0;i< *nframes; i++)    {
  295.         bitmap_index new_bmp;
  296.         sprintf( tempname, "%s#%d", fname, i );
  297.         if ( iff_has_transparency )
  298.             gr_remap_bitmap_good( bm[i], newpal, iff_transparent_color, SuperX );
  299.         else
  300.             gr_remap_bitmap_good( bm[i], newpal, -1, SuperX );
  301.  
  302.         bm[i]->avg_color = compute_average_pixel(bm[i]);
  303.  
  304.         new_bmp = piggy_register_bitmap( bm[i], tempname, 0 );
  305.         free( bm[i] );
  306.         bmp[i] = new_bmp;
  307.         mprintf((0, "Registering frame %d, %s, in piggy file\n", i, tempname ));
  308.     }
  309. }
  310.  
  311. int ds_load( char * filename )    {
  312.     int i;
  313.     CFILE * cfp;
  314.     digi_sound new;
  315.     char fname[20];
  316.     char rawname[100];
  317.  
  318. #ifdef SHAREWARE
  319.     if (Registered_only) {
  320.         //mprintf( 0, "Skipping registered-only sound '%s'\n", filename );
  321.         return &bogus_sound;
  322.     }
  323. #endif
  324.  
  325.     _splitpath(  filename, NULL, NULL, fname, NULL );
  326.     _makepath( rawname, NULL, NULL,fname, ".RAW" );
  327.  
  328.     i=piggy_find_sound( fname );
  329.     if (i!=255)    {
  330.         return i;
  331.     }
  332.  
  333.     cfp = cfopen( rawname, "rb" );
  334.  
  335.     if (cfp!=NULL) {
  336.         new.length    = cfilelength( cfp );
  337.         //MALLOC( new.data, ubyte, new.length );//hack by KRB
  338.         new.data = (ubyte *)malloc(new.length*sizeof(ubyte));
  339.         cfread( new.data, 1, new.length, cfp );
  340.         cfclose(cfp);
  341.         mprintf( (0, "S" ));
  342.         mprintf( (0, "<%s>", rawname ));
  343.     } else {
  344.         mprintf( (1, "Warning: Couldn't find '%s'\n", filename ));
  345.         return 255;
  346.     }
  347.     i = piggy_register_sound( &new, fname, 0 );
  348.     return i;
  349. }
  350.  
  351. //parse a float
  352. float get_float()
  353. {
  354.     char *xarg;
  355.  
  356.     xarg = strtok( NULL, space );
  357.     return atof( xarg );
  358. }
  359.  
  360. //parse an int
  361. int get_int()
  362. {
  363.     char *xarg;
  364.  
  365.     xarg = strtok( NULL, space );
  366.     return atoi( xarg );
  367. }
  368.  
  369. // rotates a byte left one bit, preserving the bit falling off the right
  370. //void
  371. //rotate_left(char *c)
  372. //{
  373. //    int found;
  374. //
  375. //    found = 0;
  376. //    if (*c & 0x80)
  377. //        found = 1;
  378. //    *c = *c << 1;
  379. //    if (found)
  380. //        *c |= 0x01;
  381. //}
  382.  
  383. #define LINEBUF_SIZE 600
  384.  
  385. int    linenum;
  386.  
  387. //-----------------------------------------------------------------
  388. // Initializes all bitmaps from BITMAPS.TBL file.
  389. int bm_init_use_tbl()
  390. {
  391.     CFILE    * InfoFile;
  392.     char    inputline[LINEBUF_SIZE];
  393.     int    i, have_bin_tbl;
  394.  
  395.     init_polygon_models();
  396.  
  397.     ObjType[0] = OL_PLAYER;
  398.     ObjId[0] = 0;
  399.     Num_total_object_types = 1;
  400.  
  401.     for (i=0; i<MAX_SOUNDS; i++ )    {
  402.         Sounds[i] = 255;
  403.         AltSounds[i] = 255;
  404.     }
  405.  
  406.     for (i=0; i<MAX_TEXTURES; i++ ) {
  407.         TmapInfo[i].eclip_num = -1;
  408.         TmapInfo[i].flags = 0;
  409.     }
  410.  
  411.     #ifndef SHAREWARE
  412.     for (i=0; i<MAX_HOSTAGES; i++ )
  413.         Hostage_face_clip[i].num_frames=0;
  414.     #endif
  415.  
  416.     Num_effects = 0;
  417.     for (i=0; i<MAX_EFFECTS; i++ ) {
  418.         //Effects[i].bm_ptr = (grs_bitmap **) -1;
  419.         Effects[i].changing_wall_texture = -1;
  420.         Effects[i].changing_object_texture = -1;
  421.         Effects[i].segnum = -1;
  422.         Effects[i].vc.num_frames = -1;        //another mark of being unused
  423.     }
  424.  
  425.     for (i=0;i<MAX_POLYGON_MODELS;i++)
  426.         Dying_modelnums[i] = Dead_modelnums[i] = -1;
  427.  
  428.     Num_vclips = 0;
  429.     for (i=0; i<VCLIP_MAXNUM; i++ )    {
  430.         Vclip[i].num_frames = -1;
  431.         Vclip[i].flags = 0;
  432.     }
  433.  
  434.     for (i=0; i<MAX_WALL_ANIMS; i++ )
  435.         WallAnims[i].num_frames = -1;
  436.     Num_wall_anims = 0;
  437.  
  438.     setbuf(stdout, NULL);    // unbuffered output via printf
  439.  
  440.     if (Installed)
  441.         return 1;
  442.  
  443.     Installed = 1;
  444.  
  445.     piggy_init();
  446.  
  447.     if ( FindArg( "-nobm" ) )    {
  448.         piggy_read_sounds();
  449.         return 0;
  450.     }
  451.  
  452.     // Open BITMAPS.TBL for reading.
  453.     have_bin_tbl = 0;
  454.     InfoFile = cfopen( "BITMAPS.TBL", "rb" );
  455.     if (InfoFile == NULL) {
  456.         InfoFile = cfopen("BITMAPS.BIN", "rb");
  457.         if (InfoFile == NULL)
  458.             Error("Missing BITMAPS.TBL and BITMAPS.BIN file\n");
  459.         have_bin_tbl = 1;
  460.     }
  461.     linenum = 0;
  462.     
  463.     cfseek( InfoFile, 0L, SEEK_SET);
  464.  
  465.     while (cfgets(inputline, LINEBUF_SIZE, InfoFile)) {
  466.         int l;
  467.         char *temp_ptr;
  468.  
  469.         linenum++;
  470.  
  471.         if (have_bin_tbl) {                // is this a binary tbl file
  472.             for (i = 0; i < strlen(inputline) - 1; i++) {
  473.                 encode_rotate_left(&(inputline[i]));
  474.                 inputline[i] = inputline[i] ^ BITMAP_TBL_XOR;
  475.                 encode_rotate_left(&(inputline[i]));
  476.             }
  477.         } else {
  478.             while (inputline[(l=strlen(inputline))-2]=='\\') {
  479.                 cfgets(inputline+l-2,LINEBUF_SIZE-(l-2), InfoFile);
  480.                 linenum++;
  481.             }
  482.         }
  483.  
  484.         REMOVE_EOL(inputline);
  485.         if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
  486.  
  487.         if (strlen(inputline) == LINEBUF_SIZE-1)
  488.             Error("Possible line truncation in BITMAPS.TBL on line %d\n",linenum);
  489.  
  490.         SuperX = -1;
  491.  
  492.         if ( (temp_ptr=strstr( inputline, "superx=" )) )    {
  493.             SuperX = atoi( &temp_ptr[7] );
  494.         }
  495.  
  496.         arg = strtok( inputline, space );
  497.         if (arg[0] == '@') {
  498.             arg++;
  499.             Registered_only = 1;
  500.         } else
  501.             Registered_only = 0;
  502.  
  503.         while (arg != NULL )
  504.             {
  505.             // Check all possible flags and defines.
  506.             if (*arg == '$') bm_flag = BM_NONE; // reset to no flags as default.
  507.  
  508.             IFTOK("$COCKPIT")             bm_flag = BM_COCKPIT;
  509.             else IFTOK("$GAUGES")        {bm_flag = BM_GAUGES;   clip_count = 0;}
  510.             else IFTOK("$SOUND")         bm_read_sound();
  511.             else IFTOK("$DOOR_ANIMS")    bm_flag = BM_WALL_ANIMS;
  512.             else IFTOK("$WALL_ANIMS")    bm_flag = BM_WALL_ANIMS;
  513.             else IFTOK("$TEXTURES")     bm_flag = BM_TEXTURES;
  514.             else IFTOK("$VCLIP")            {bm_flag = BM_VCLIP;        vlighting = 0;    clip_count = 0;}
  515.             else IFTOK("$ECLIP")            {bm_flag = BM_ECLIP;        vlighting = 0;    clip_count = 0; obj_eclip=0; dest_bm=NULL; dest_vclip=-1; dest_eclip=-1; dest_size=-1; crit_clip=-1; crit_flag=0; sound_num=-1;}
  516.             else IFTOK("$WCLIP")            {bm_flag = BM_WCLIP;        vlighting = 0;    clip_count = 0; wall_explodes = wall_blastable = 0; wall_open_sound=wall_close_sound=-1; tmap1_flag=0; wall_hidden=0;}
  517.  
  518.             else IFTOK("$EFFECTS")        {bm_flag = BM_EFFECTS;    clip_num = 0;}
  519.  
  520.             #ifdef EDITOR
  521.             else IFTOK("!METALS_FLAG")        TextureMetals = texture_count;
  522.             else IFTOK("!LIGHTS_FLAG")        TextureLights = texture_count;
  523.             else IFTOK("!EFFECTS_FLAG")    TextureEffects = texture_count;
  524.             #endif
  525.  
  526.             else IFTOK("lighting")             TmapInfo[texture_count-1].lighting = fl2f(get_float());
  527.             else IFTOK("damage")             TmapInfo[texture_count-1].damage = fl2f(get_float());
  528.             else IFTOK("volatile")             TmapInfo[texture_count-1].flags |= TMI_VOLATILE;
  529.             //else IFTOK("Num_effects")        Num_effects = get_int();
  530.             else IFTOK("Num_wall_anims")    Num_wall_anims = get_int();
  531.             else IFTOK("clip_num")            clip_num = get_int();
  532.             else IFTOK("dest_bm")            dest_bm = strtok( NULL, space );
  533.             else IFTOK("dest_vclip")        dest_vclip = get_int();
  534.             else IFTOK("dest_eclip")        dest_eclip = get_int();
  535.             else IFTOK("dest_size")            dest_size = fl2f(get_float());
  536.             else IFTOK("crit_clip")            crit_clip = get_int();
  537.             else IFTOK("crit_flag")            crit_flag = get_int();
  538.             else IFTOK("sound_num")         sound_num = get_int();
  539.             else IFTOK("frames")             frames = get_int();
  540.             else IFTOK("time")                 time = get_float();
  541.             else IFTOK("obj_eclip")            obj_eclip = get_int();
  542.             else IFTOK("hit_sound")         hit_sound = get_int();
  543.             else IFTOK("abm_flag")            abm_flag = get_int();
  544.             else IFTOK("tmap1_flag")        tmap1_flag = get_int();
  545.             else IFTOK("vlighting")            vlighting = get_float();
  546.             else IFTOK("rod_flag")            rod_flag = get_int();
  547.             else IFTOK("superx")             get_int();
  548.             else IFTOK("open_sound")         wall_open_sound = get_int();
  549.             else IFTOK("close_sound")         wall_close_sound = get_int();
  550.             else IFTOK("explodes")             wall_explodes = get_int();
  551.             else IFTOK("blastable")             wall_blastable = get_int();
  552.             else IFTOK("hidden")                 wall_hidden = get_int();
  553.             else IFTOK("$ROBOT_AI")         bm_read_robot_ai();
  554.  
  555.             else IFTOK("$POWERUP")            {bm_read_powerup(0);        continue;}
  556.             else IFTOK("$POWERUP_UNUSED")    {bm_read_powerup(1);        continue;}
  557.             else IFTOK("$HOSTAGE")            {bm_read_hostage();        continue;}
  558.             else IFTOK("$HOSTAGE_FACE")    {bm_read_hostage_face();continue;}
  559.             else IFTOK("$ROBOT")                {bm_read_robot();            continue;}
  560.             else IFTOK("$WEAPON")            {bm_read_weapon(0);        continue;}
  561.             else IFTOK("$WEAPON_UNUSED")    {bm_read_weapon(1);        continue;}
  562.             else IFTOK("$OBJECT")            {bm_read_object();        continue;}
  563.             else IFTOK("$PLAYER_SHIP")        {bm_read_player_ship();    continue;}
  564.  
  565.             else    {        //not a special token, must be a bitmap!
  566.  
  567.                 // Remove any illegal/unwanted spaces and tabs at this point.
  568.                 while ((*arg=='\t') || (*arg==' ')) arg++;
  569.                 if (*arg == '\0') { break; }    
  570.  
  571.                 // Otherwise, 'arg' is apparently a bitmap filename.
  572.                 // Load bitmap and process it below:
  573.                 bm_read_some_file();
  574.  
  575.             }
  576.  
  577.             arg = strtok( NULL, equal_space );
  578.             continue;
  579.       }
  580.     }
  581.  
  582.     NumTextures = texture_count;
  583.     Num_tmaps = tmap_count;
  584.     
  585.     cfclose( InfoFile );
  586.  
  587.     atexit(bm_close);
  588.  
  589.     Assert(N_robot_types == Num_robot_ais);        //should be one ai info per robot
  590.  
  591.     init_endlevel();        //this is here so endlevel bitmaps go into pig
  592.     
  593.     verify_textures();
  594.  
  595.     //check for refereced but unused clip count
  596.     for (i=0; i<MAX_EFFECTS; i++ )
  597.         if (    (
  598.                   (Effects[i].changing_wall_texture!=-1) ||
  599.                   (Effects[i].changing_object_texture!=-1)     
  600.              )
  601.              && (Effects[i].vc.num_frames==-1) )
  602.             Error("EClip %d referenced (by polygon object?), but not defined",i);
  603.  
  604.     #ifndef NDEBUG
  605.     {
  606.         int used;
  607.         for (i=used=0; i<num_sounds; i++ )
  608.             if (Sounds[i] != 255)
  609.                 used++;
  610.         mprintf((0,"Sound slots used: %d of %d, highest index %d\n",used,MAX_SOUNDS,num_sounds));
  611.     }
  612.     #endif
  613.  
  614.     piggy_read_sounds();
  615.  
  616.     #ifdef EDITOR
  617.     piggy_dump_all();
  618.     #endif
  619.  
  620.     return 0;
  621. }
  622.  
  623. void verify_textures()
  624. {
  625.     grs_bitmap * bmp;
  626.     int i,j;
  627.     j=0;
  628.     for (i=0; i<Num_tmaps; i++ )    {
  629.         bmp = &GameBitmaps[Textures[i].index];
  630.         if ( (bmp->bm_w!=64)||(bmp->bm_h!=64)||(bmp->bm_rowsize!=64) )    {
  631.             mprintf( (1, "ERROR: Texture '%s' isn't 64x64 !\n", TmapInfo[i].filename ));
  632.             j++;
  633.         } 
  634.     }
  635.     if (j) exit(1);
  636. }
  637.  
  638. //--unused-- void dump_all_transparent_textures()
  639. //--unused-- {
  640. //--unused--     FILE * fp;
  641. //--unused--     int i,j,k;
  642. //--unused--     ubyte * p;
  643. //--unused--     fp = fopen( "XPARENT.LST", "wt" );
  644. //--unused--     for (i=0; i<Num_tmaps; i++ )    {
  645. //--unused--         k = 0; 
  646. //--unused--         p = Textures[i]->bm_data;
  647. //--unused--         for (j=0; j<64*64; j++ )
  648. //--unused--             if ( (*p++)==255 ) k++;
  649. //--unused--         if ( k )    {
  650. //--unused--             fprintf( fp, "'%s' has %d transparent pixels\n", TmapInfo[i].filename, k );
  651. //--unused--         }                
  652. //--unused--     }
  653. //--unused--     fclose(fp);    
  654. //--unused-- }
  655.  
  656.  
  657. void bm_close()
  658. {
  659.     if (Installed)
  660.     {
  661.         piggy_close();
  662.         Installed=0;
  663.      }
  664. }
  665.  
  666. void set_lighting_flag(byte *bp)
  667. {
  668.     if (vlighting < 0)
  669.         *bp |= BM_FLAG_NO_LIGHTING;
  670.     else
  671.         *bp &= (0xff ^ BM_FLAG_NO_LIGHTING);
  672. }
  673.  
  674. set_texture_name(char *name)
  675. {
  676.     strcpy ( TmapInfo[texture_count].filename, name );
  677.     REMOVE_DOTS(TmapInfo[texture_count].filename);
  678. }
  679.  
  680. void bm_read_eclip()
  681. {
  682.     bitmap_index bitmap;
  683.  
  684.     Assert(clip_num < MAX_EFFECTS);
  685.  
  686.     if (clip_num+1 > Num_effects)
  687.         Num_effects = clip_num+1;
  688.  
  689.     Effects[clip_num].flags = 0;
  690.  
  691.     if (!abm_flag)    { 
  692.         bitmap = bm_load_sub(arg);
  693.  
  694.         Effects[clip_num].vc.play_time = fl2f(time);
  695.         Effects[clip_num].vc.num_frames = frames;
  696.         Effects[clip_num].vc.frame_time = fl2f(time)/frames;
  697.  
  698.         Assert(clip_count < frames);
  699.         Effects[clip_num].vc.frames[clip_count] = bitmap;
  700.         set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags);
  701.  
  702.         Assert(!obj_eclip);        //obj eclips for non-abm files not supported!
  703.         Assert(crit_flag==0);
  704.  
  705.         if (clip_count == 0) {
  706.             Effects[clip_num].changing_wall_texture = texture_count;
  707.             Assert(tmap_count < MAX_TEXTURES);
  708.               TmapList[tmap_count++] = texture_count;
  709.             Textures[texture_count] = bitmap;
  710.             set_texture_name(arg);
  711.             Assert(texture_count < MAX_TEXTURES);
  712.             texture_count++;
  713.             TmapInfo[texture_count].eclip_num = clip_num;
  714.             NumTextures = texture_count;
  715.         }
  716.  
  717.         clip_count++;
  718.  
  719.     } else {
  720.         bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
  721.         abm_flag = 0;
  722.  
  723.         ab_load( arg, bm, &Effects[clip_num].vc.num_frames );
  724.  
  725.         //printf("EC%d.", clip_num);
  726.         Effects[clip_num].vc.play_time = fl2f(time);
  727.         Effects[clip_num].vc.frame_time = Effects[clip_num].vc.play_time/Effects[clip_num].vc.num_frames;
  728.  
  729.         clip_count = 0;    
  730.         set_lighting_flag( &GameBitmaps[bm[clip_count].index].bm_flags);
  731.         Effects[clip_num].vc.frames[clip_count] = bm[clip_count];
  732.  
  733.         if (!obj_eclip && !crit_flag) {
  734.             Effects[clip_num].changing_wall_texture = texture_count;
  735.             Assert(tmap_count < MAX_TEXTURES);
  736.               TmapList[tmap_count++] = texture_count;
  737.             Textures[texture_count] = bm[clip_count];
  738.             set_texture_name( arg );
  739.             Assert(texture_count < MAX_TEXTURES);
  740.             TmapInfo[texture_count].eclip_num = clip_num;
  741.             texture_count++;
  742.             NumTextures = texture_count;
  743.         }
  744.  
  745.         if (obj_eclip) {
  746.  
  747.             if (Effects[clip_num].changing_object_texture == -1) {        //first time referenced
  748.                 Effects[clip_num].changing_object_texture = N_ObjBitmaps;        // XChange ObjectBitmaps
  749.                 N_ObjBitmaps++;
  750.             }
  751.  
  752.             ObjBitmaps[Effects[clip_num].changing_object_texture] = Effects[clip_num].vc.frames[0];
  753.         }
  754.  
  755.         //if for an object, Effects_bm_ptrs set in object load 
  756.  
  757.         for(clip_count=1;clip_count < Effects[clip_num].vc.num_frames; clip_count++) {
  758.             set_lighting_flag( &GameBitmaps[bm[clip_count].index].bm_flags);
  759.             Effects[clip_num].vc.frames[clip_count] = bm[clip_count];
  760.         }
  761.  
  762.     }
  763.  
  764.     Effects[clip_num].crit_clip = crit_clip;
  765.     Effects[clip_num].sound_num = sound_num;
  766.  
  767.     if (dest_bm) {            //deal with bitmap for blown up clip
  768.         char short_name[13];
  769.         int i;
  770.         strcpy(short_name,dest_bm);
  771.         REMOVE_DOTS(short_name);
  772.         for (i=0;i<texture_count;i++)
  773.             if (!stricmp(TmapInfo[i].filename,short_name))
  774.                 break;
  775.         if (i==texture_count) {
  776.             Textures[texture_count] = bm_load_sub(dest_bm);
  777.             strcpy( TmapInfo[texture_count].filename, short_name);
  778.             texture_count++;
  779.             Assert(texture_count < MAX_TEXTURES);
  780.             NumTextures = texture_count;
  781.         }
  782.         Effects[clip_num].dest_bm_num = i;
  783.  
  784.         if (dest_vclip==-1)
  785.             Error("Desctuction vclip missing on line %d",linenum);
  786.         if (dest_size==-1)
  787.             Error("Desctuction vclip missing on line %d",linenum);
  788.  
  789.         Effects[clip_num].dest_vclip = dest_vclip;
  790.         Effects[clip_num].dest_size = dest_size;
  791.  
  792.         Effects[clip_num].dest_eclip = dest_eclip;
  793.     }
  794.     else {
  795.         Effects[clip_num].dest_bm_num = -1;
  796.         Effects[clip_num].dest_eclip = -1;
  797.     }
  798.  
  799.     if (crit_flag)
  800.         Effects[clip_num].flags |= EF_CRITICAL;
  801. }
  802.  
  803.  
  804. void bm_read_gauges()
  805. {
  806.     bitmap_index bitmap;
  807.     int i, num_abm_frames;
  808.  
  809.     if (!abm_flag)    { 
  810.         bitmap = bm_load_sub(arg);
  811.         Assert(clip_count < MAX_GAUGE_BMS);
  812.         Gauges[clip_count] = bitmap;
  813.         clip_count++;
  814.     } else {
  815.         bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
  816.         abm_flag = 0;
  817.         ab_load( arg, bm, &num_abm_frames );
  818.         for (i=clip_count; i<clip_count+num_abm_frames; i++) {
  819.             Assert(i < MAX_GAUGE_BMS);
  820.             Gauges[i] = bm[i-clip_count];
  821.         }
  822.         clip_count += num_abm_frames;
  823.     }
  824. }
  825.  
  826. void bm_read_wclip()
  827. {
  828.     bitmap_index bitmap;
  829.     Assert(clip_num < MAX_WALL_ANIMS);
  830.  
  831.     WallAnims[clip_num].flags = 0;
  832.  
  833.     if (wall_explodes)    WallAnims[clip_num].flags |= WCF_EXPLODES;
  834.     if (wall_blastable)    WallAnims[clip_num].flags |= WCF_BLASTABLE;
  835.     if (wall_hidden)        WallAnims[clip_num].flags |= WCF_HIDDEN;
  836.     if (tmap1_flag)        WallAnims[clip_num].flags |= WCF_TMAP1;
  837.  
  838.     if (!abm_flag)    {
  839.         bitmap = bm_load_sub(arg);
  840.         if ( (WallAnims[clip_num].num_frames>-1) && (clip_count==0) )
  841.             Error( "Wall Clip %d is already used!", clip_num );
  842.         WallAnims[clip_num].play_time = fl2f(time);
  843.         WallAnims[clip_num].num_frames = frames;
  844.         //WallAnims[clip_num].frame_time = fl2f(time)/frames;
  845.         Assert(clip_count < frames);
  846.         WallAnims[clip_num].frames[clip_count++] = texture_count;
  847.         WallAnims[clip_num].open_sound = wall_open_sound;
  848.         WallAnims[clip_num].close_sound = wall_close_sound;
  849.         Textures[texture_count] = bitmap;
  850.         set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags);
  851.         set_texture_name( arg );
  852.         Assert(texture_count < MAX_TEXTURES);
  853.         texture_count++;
  854.         NumTextures = texture_count;
  855.         if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1;
  856.     } else {
  857.         bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
  858.         int nframes;
  859.         if ( (WallAnims[clip_num].num_frames>-1)  )
  860.             Error( "AB_Wall clip %d is already used!", clip_num );
  861.         abm_flag = 0;
  862.         ab_load( arg, bm, &nframes );
  863.         WallAnims[clip_num].num_frames = nframes;
  864.         //printf("WC");
  865.         WallAnims[clip_num].play_time = fl2f(time);
  866.         //WallAnims[clip_num].frame_time = fl2f(time)/nframes;
  867.         WallAnims[clip_num].open_sound = wall_open_sound;
  868.         WallAnims[clip_num].close_sound = wall_close_sound;
  869.  
  870.         WallAnims[clip_num].close_sound = wall_close_sound;
  871.         strcpy(WallAnims[clip_num].filename, arg);
  872.         REMOVE_DOTS(WallAnims[clip_num].filename);    
  873.  
  874.         if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1;
  875.  
  876.         set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
  877.  
  878.         for (clip_count=0;clip_count < WallAnims[clip_num].num_frames; clip_count++)    {
  879.             //printf("%d", clip_count);
  880.             Textures[texture_count] = bm[clip_count];
  881.             set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
  882.             WallAnims[clip_num].frames[clip_count] = texture_count;
  883.             REMOVE_DOTS(arg);
  884.             sprintf( TmapInfo[texture_count].filename, "%s#%d", arg, clip_count);
  885.             Assert(texture_count < MAX_TEXTURES);
  886.             texture_count++;
  887.             NumTextures = texture_count;
  888.         }
  889.     }
  890. }
  891.  
  892. void bm_read_vclip()
  893. {
  894.     bitmap_index bi;
  895.     Assert(clip_num < VCLIP_MAXNUM);
  896.  
  897.     if (!abm_flag)    {
  898.         if ( (Vclip[clip_num].num_frames>-1) && (clip_count==0)  )
  899.             Error( "Vclip %d is already used!", clip_num );
  900.         bi = bm_load_sub(arg);
  901.         Vclip[clip_num].play_time = fl2f(time);
  902.         Vclip[clip_num].num_frames = frames;
  903.         Vclip[clip_num].frame_time = fl2f(time)/frames;
  904.         Vclip[clip_num].light_value = fl2f(vlighting);
  905.         Vclip[clip_num].sound_num = sound_num;
  906.         set_lighting_flag(&GameBitmaps[bi.index].bm_flags);
  907.         Assert(clip_count < frames);
  908.         Vclip[clip_num].frames[clip_count++] = bi;
  909.         if (rod_flag) {
  910.             rod_flag=0;
  911.             Vclip[clip_num].flags |= VF_ROD;
  912.         }            
  913.  
  914.     } else    {
  915.         bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
  916.         abm_flag = 0;
  917.         if ( (Vclip[clip_num].num_frames>-1)  )
  918.             Error( "AB_Vclip %d is already used!", clip_num );
  919.         ab_load( arg, bm, &Vclip[clip_num].num_frames );
  920.  
  921.         if (rod_flag) {
  922.             //int i;
  923.             rod_flag=0;
  924.             Vclip[clip_num].flags |= VF_ROD;
  925.         }            
  926.         //printf("VC");
  927.         Vclip[clip_num].play_time = fl2f(time);
  928.         Vclip[clip_num].frame_time = fl2f(time)/Vclip[clip_num].num_frames;
  929.         Vclip[clip_num].light_value = fl2f(vlighting);
  930.         Vclip[clip_num].sound_num = sound_num;
  931.         set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
  932.  
  933.         for (clip_count=0;clip_count < Vclip[clip_num].num_frames; clip_count++) {
  934.             //printf("%d", clip_count);
  935.             set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
  936.             Vclip[clip_num].frames[clip_count] = bm[clip_count];
  937.         }
  938.     }
  939. }
  940.  
  941. // ------------------------------------------------------------------------------
  942. void get4fix(fix *fixp)
  943. {
  944.     char    *curtext;
  945.     int    i;
  946.  
  947.     for (i=0; i<NDL; i++) {
  948.         curtext = strtok(NULL, space);
  949.         fixp[i] = fl2f(atof(curtext));
  950.     }
  951. }
  952.  
  953. // ------------------------------------------------------------------------------
  954. void get4byte(byte *bytep)
  955. {
  956.     char    *curtext;
  957.     int    i;
  958.  
  959.     for (i=0; i<NDL; i++) {
  960.         curtext = strtok(NULL, space);
  961.         bytep[i] = atoi(curtext);
  962.     }
  963. }
  964.  
  965. // ------------------------------------------------------------------------------
  966. //    Convert field of view from an angle in 0..360 to cosine.
  967. void adjust_field_of_view(fix *fovp)
  968. {
  969.     int        i;
  970.     fixang    tt;
  971.     float        ff;
  972.     fix        temp;
  973.  
  974.     for (i=0; i<NDL; i++) {
  975.         ff = - f2fl(fovp[i]);
  976.         if (ff > 179) {
  977.             mprintf((1, "Warning: Bogus field of view (%7.3f).  Must be in 0..179.\n", ff));
  978.             ff = 179;
  979.         }
  980.         ff = ff/360;
  981.         tt = fl2f(ff);
  982.         fix_sincos(tt, &temp, &fovp[i]);
  983.     }
  984. }
  985.  
  986. void clear_to_end_of_line(void)
  987. {
  988.     arg = strtok( NULL, space );
  989.     while (arg != NULL)
  990.         arg = strtok( NULL, space );
  991. }
  992.  
  993. bm_read_sound()
  994. {
  995.     int sound_num;
  996.     int alt_sound_num;
  997.  
  998.     sound_num = get_int();
  999.     alt_sound_num = get_int();
  1000.  
  1001.     if ( sound_num>=MAX_SOUNDS )
  1002.         Error( "Too many sound files.\n" );
  1003.  
  1004.     if (sound_num >= num_sounds)
  1005.         num_sounds = sound_num+1;
  1006.  
  1007.     arg = strtok(NULL, space);
  1008.  
  1009.     Sounds[sound_num] = ds_load(arg);
  1010.  
  1011.     if ( alt_sound_num == 0 )
  1012.         AltSounds[sound_num] = sound_num;
  1013.     else if (alt_sound_num < 0 )
  1014.         AltSounds[sound_num] = 255;
  1015.     else
  1016.         AltSounds[sound_num] = alt_sound_num;
  1017.  
  1018.     if (Sounds[sound_num] == 255)
  1019.         Error("Can't load soundfile <%s>",arg);
  1020. }
  1021.  
  1022. // ------------------------------------------------------------------------------
  1023. void bm_read_robot_ai()    
  1024. {
  1025.     char            *robotnum_text;
  1026.     int            robotnum;
  1027.     robot_info    *robptr;
  1028.  
  1029.     robotnum_text = strtok(NULL, space);
  1030.     robotnum = atoi(robotnum_text);
  1031.     Assert(robotnum < MAX_ROBOT_TYPES);
  1032.     robptr = &Robot_info[robotnum];
  1033.  
  1034.     Assert(robotnum == Num_robot_ais);        //make sure valid number
  1035.  
  1036. #ifdef SHAREWARE
  1037.     if (Registered_only) {
  1038.         Num_robot_ais++;
  1039.         clear_to_end_of_line();
  1040.         return;
  1041.     }
  1042. #endif
  1043.  
  1044.     Num_robot_ais++;
  1045.  
  1046.     get4fix(robptr->field_of_view);
  1047.     get4fix(robptr->firing_wait);
  1048.     get4byte(robptr->rapidfire_count);
  1049.     get4fix(robptr->turn_time);
  1050.     get4fix(robptr->fire_power);
  1051.     get4fix(robptr->shield);
  1052.     get4fix(robptr->max_speed);
  1053.     get4fix(robptr->circle_distance);
  1054.     get4byte(robptr->evade_speed);
  1055.  
  1056.     robptr->always_0xabcd    = 0xabcd;
  1057.  
  1058.     adjust_field_of_view(robptr->field_of_view);
  1059.  
  1060. }
  1061.  
  1062. //    ----------------------------------------------------------------------------------------------
  1063. //this will load a bitmap for a polygon models.  it puts the bitmap into
  1064. //the array ObjBitmaps[], and also deals with animating bitmaps
  1065. //returns a pointer to the bitmap
  1066. grs_bitmap *load_polymodel_bitmap(char *name)
  1067. {
  1068.     Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
  1069.  
  1070. //    Assert( N_ObjBitmaps == N_ObjBitmapPtrs );
  1071.  
  1072.     if (name[0] == '%') {        //an animating bitmap!
  1073.         int eclip_num;
  1074.  
  1075.         eclip_num = atoi(name+1);
  1076.  
  1077.         if (Effects[eclip_num].changing_object_texture == -1) {        //first time referenced
  1078.             Effects[eclip_num].changing_object_texture = N_ObjBitmaps;
  1079.             ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps;
  1080.             N_ObjBitmaps++;
  1081.         } else {
  1082.             ObjBitmapPtrs[N_ObjBitmapPtrs++] = Effects[eclip_num].changing_object_texture;
  1083.         }
  1084.         return NULL;
  1085.     }
  1086.     else     {
  1087.         ObjBitmaps[N_ObjBitmaps] = bm_load_sub(name);
  1088.         ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps;
  1089.         N_ObjBitmaps++;
  1090.         return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index];
  1091.     }
  1092. }
  1093.  
  1094. #define MAX_MODEL_VARIANTS    4
  1095.  
  1096. // ------------------------------------------------------------------------------
  1097. void bm_read_robot()    
  1098. {
  1099.     char            *model_name[MAX_MODEL_VARIANTS];
  1100.     int            n_models,i;
  1101.     int            first_bitmap_num[MAX_MODEL_VARIANTS];
  1102.     char            *equal_ptr;
  1103.     int             exp1_vclip_num=-1;
  1104.     int            exp1_sound_num=-1;
  1105.     int             exp2_vclip_num=-1;
  1106.     int            exp2_sound_num=-1;
  1107.     fix            lighting = F1_0/2;        // Default
  1108.     fix            strength = F1_0*10;        // Default strength
  1109.     fix            mass = f1_0*4;
  1110.     fix            drag = f1_0/2;
  1111.     short         weapon_type = 0;
  1112.     int            g,s;
  1113.     char            name[ROBOT_NAME_LENGTH];
  1114.     int            contains_count=0, contains_id=0, contains_prob=0, contains_type=0;
  1115.     int            score_value=1000;
  1116.     int            cloak_type=0;        //    Default = this robot does not cloak
  1117.     int            attack_type=0;        //    Default = this robot attacks by firing (1=lunge)
  1118.     int            boss_flag=0;                //    Default = robot is not a boss.
  1119.     int            see_sound = ROBOT_SEE_SOUND_DEFAULT;
  1120.     int            attack_sound = ROBOT_ATTACK_SOUND_DEFAULT;
  1121.     int            claw_sound = ROBOT_CLAW_SOUND_DEFAULT;
  1122.  
  1123.     Assert(N_robot_types < MAX_ROBOT_TYPES);
  1124.  
  1125. #ifdef SHAREWARE
  1126.     if (Registered_only) {
  1127.         Robot_info[N_robot_types].model_num = -1;
  1128.         N_robot_types++;
  1129.         Num_total_object_types++;
  1130.         clear_to_end_of_line();
  1131.         return;
  1132.     }
  1133. #endif
  1134.  
  1135.     model_name[0] = strtok( NULL, space );
  1136.     first_bitmap_num[0] = N_ObjBitmapPtrs;
  1137.     n_models = 1;
  1138.  
  1139.     // Process bitmaps 
  1140.     bm_flag=BM_ROBOT;
  1141.     arg = strtok( NULL, space ); 
  1142.     while (arg!=NULL)    {
  1143.         equal_ptr = strchr( arg, '=' );
  1144.         if ( equal_ptr )    {
  1145.             *equal_ptr='\0';
  1146.             equal_ptr++;
  1147.             // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
  1148.             if (!stricmp( arg, "exp1_vclip" ))    {
  1149.                 exp1_vclip_num = atoi(equal_ptr);
  1150.             } else if (!stricmp( arg, "exp2_vclip" ))    {
  1151.                 exp2_vclip_num = atoi(equal_ptr);
  1152.             } else if (!stricmp( arg, "exp1_sound" ))    {
  1153.                 exp1_sound_num = atoi(equal_ptr);
  1154.             } else if (!stricmp( arg, "exp2_sound" ))    {
  1155.                 exp2_sound_num = atoi(equal_ptr);
  1156.             } else if (!stricmp( arg, "lighting" ))    {
  1157.                 lighting = fl2f(atof(equal_ptr));
  1158.                 if ( (lighting < 0) || (lighting > F1_0 )) {
  1159.                     mprintf( (1, "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)));
  1160.                     Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting));
  1161.                 }
  1162.             } else if (!stricmp( arg, "weapon_type" )) {
  1163.                 weapon_type = atoi(equal_ptr);
  1164.             } else if (!stricmp( arg, "strength" )) {
  1165.                 strength = i2f(atoi(equal_ptr));
  1166.             } else if (!stricmp( arg, "mass" )) {
  1167.                 mass = fl2f(atof(equal_ptr));
  1168.             } else if (!stricmp( arg, "drag" )) {
  1169.                 drag = fl2f(atof(equal_ptr));
  1170.             } else if (!stricmp( arg, "contains_id" )) {
  1171.                 contains_id = atoi(equal_ptr);
  1172.             } else if (!stricmp( arg, "contains_type" )) {
  1173.                 contains_type = atoi(equal_ptr);
  1174.             } else if (!stricmp( arg, "contains_count" )) {
  1175.                 contains_count = atoi(equal_ptr);
  1176.             } else if (!stricmp( arg, "contains_prob" )) {
  1177.                 contains_prob = atoi(equal_ptr);
  1178.             } else if (!stricmp( arg, "cloak_type" )) {
  1179.                 cloak_type = atoi(equal_ptr);
  1180.             } else if (!stricmp( arg, "attack_type" )) {
  1181.                 attack_type = atoi(equal_ptr);
  1182.             } else if (!stricmp( arg, "boss" )) {
  1183.                 boss_flag = atoi(equal_ptr);
  1184.             } else if (!stricmp( arg, "score_value" )) {
  1185.                 score_value = atoi(equal_ptr);
  1186.             } else if (!stricmp( arg, "see_sound" )) {
  1187.                 see_sound = atoi(equal_ptr);
  1188.             } else if (!stricmp( arg, "attack_sound" )) {
  1189.                 attack_sound = atoi(equal_ptr);
  1190.             } else if (!stricmp( arg, "claw_sound" )) {
  1191.                 claw_sound = atoi(equal_ptr);
  1192.             } else if (!stricmp( arg, "name" )) {
  1193.                 Assert(strlen(equal_ptr) < ROBOT_NAME_LENGTH);    //    Oops, name too long.
  1194.                 strcpy(name, &equal_ptr[1]);
  1195.                 name[strlen(name)-1] = 0;
  1196.             } else if (!stricmp( arg, "simple_model" )) {
  1197.                 model_name[n_models] = equal_ptr;
  1198.                 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
  1199.                 n_models++;
  1200.             } else {
  1201.                 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
  1202.             }        
  1203.         } else {            // Must be a texture specification...
  1204.             load_polymodel_bitmap(arg);
  1205.         }
  1206.         arg = strtok( NULL, space );
  1207.     }
  1208.  
  1209.     //clear out anim info
  1210.     for (g=0;g<MAX_GUNS+1;g++)
  1211.         for (s=0;s<N_ANIM_STATES;s++)
  1212.             Robot_info[N_robot_types].anim_states[g][s].n_joints = 0;    //inialize to zero
  1213.  
  1214.     first_bitmap_num[n_models] = N_ObjBitmapPtrs;
  1215.  
  1216.     for (i=0;i<n_models;i++) {
  1217.         int n_textures;
  1218.         int model_num,last_model_num;
  1219.  
  1220.         n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
  1221.  
  1222.         model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],(i==0)?&Robot_info[N_robot_types]:NULL);
  1223.  
  1224.         if (i==0)
  1225.             Robot_info[N_robot_types].model_num = model_num;
  1226.         else
  1227.             Polygon_models[last_model_num].simpler_model = model_num+1;
  1228.  
  1229.         last_model_num = model_num;
  1230.     }
  1231.  
  1232.     ObjType[Num_total_object_types] = OL_ROBOT;
  1233.     ObjId[Num_total_object_types] = N_robot_types;
  1234.  
  1235.     Robot_info[N_robot_types].exp1_vclip_num = exp1_vclip_num;
  1236.     Robot_info[N_robot_types].exp2_vclip_num = exp2_vclip_num;
  1237.     Robot_info[N_robot_types].exp1_sound_num = exp1_sound_num;
  1238.     Robot_info[N_robot_types].exp2_sound_num = exp2_sound_num;
  1239.     Robot_info[N_robot_types].lighting = lighting;
  1240.     Robot_info[N_robot_types].weapon_type = weapon_type;
  1241.     Robot_info[N_robot_types].strength = strength;
  1242.     Robot_info[N_robot_types].mass = mass;
  1243.     Robot_info[N_robot_types].drag = drag;
  1244.     Robot_info[N_robot_types].cloak_type = cloak_type;
  1245.     Robot_info[N_robot_types].attack_type = attack_type;
  1246.     Robot_info[N_robot_types].boss_flag = boss_flag;
  1247.  
  1248.     Robot_info[N_robot_types].contains_id = contains_id;
  1249.     Robot_info[N_robot_types].contains_count = contains_count;
  1250.     Robot_info[N_robot_types].contains_prob = contains_prob;
  1251.     Robot_info[N_robot_types].score_value = score_value;
  1252.     Robot_info[N_robot_types].see_sound = see_sound;
  1253.     Robot_info[N_robot_types].attack_sound = attack_sound;
  1254.     Robot_info[N_robot_types].claw_sound = claw_sound;
  1255.  
  1256.     if (contains_type)
  1257.         Robot_info[N_robot_types].contains_type = OBJ_ROBOT;
  1258.     else
  1259.         Robot_info[N_robot_types].contains_type = OBJ_POWERUP;
  1260.  
  1261.     strcpy(Robot_names[N_robot_types], name);
  1262.  
  1263.     N_robot_types++;
  1264.     Num_total_object_types++;
  1265. }
  1266.  
  1267. //read a polygon object of some sort
  1268. void bm_read_object()
  1269. {
  1270.     char *model_name, *model_name_dead=NULL;
  1271.     int first_bitmap_num, first_bitmap_num_dead, n_normal_bitmaps;
  1272.     char *equal_ptr;
  1273.     short model_num;
  1274.     short explosion_vclip_num = -1;
  1275.     short explosion_sound_num = SOUND_ROBOT_DESTROYED;
  1276.     fix    lighting = F1_0/2;        // Default
  1277.     int type=-1;
  1278.     fix strength=0;
  1279.  
  1280.     model_name = strtok( NULL, space );
  1281.  
  1282.     // Process bitmaps 
  1283.     bm_flag = BM_NONE;
  1284.     arg = strtok( NULL, space ); 
  1285.     first_bitmap_num = N_ObjBitmapPtrs;
  1286.  
  1287.     while (arg!=NULL)    {
  1288.  
  1289.         equal_ptr = strchr( arg, '=' );
  1290.  
  1291.         if ( equal_ptr )    {
  1292.             *equal_ptr='\0';
  1293.             equal_ptr++;
  1294.  
  1295.             // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
  1296.  
  1297.             if (!stricmp(arg,"type")) {
  1298.                 if (!stricmp(equal_ptr,"controlcen"))
  1299.                     type = OL_CONTROL_CENTER;
  1300.                 else if (!stricmp(equal_ptr,"clutter"))
  1301.                     type = OL_CLUTTER;
  1302.                 else if (!stricmp(equal_ptr,"exit"))
  1303.                     type = OL_EXIT;
  1304.             }
  1305.             else if (!stricmp( arg, "exp_vclip" ))    {
  1306.                 explosion_vclip_num = atoi(equal_ptr);
  1307.             } else if (!stricmp( arg, "dead_pof" ))    {
  1308.                 model_name_dead = equal_ptr;
  1309.                 first_bitmap_num_dead=N_ObjBitmapPtrs;
  1310.             } else if (!stricmp( arg, "exp_sound" ))    {
  1311.                 explosion_sound_num = atoi(equal_ptr);
  1312.             } else if (!stricmp( arg, "lighting" ))    {
  1313.                 lighting = fl2f(atof(equal_ptr));
  1314.                 if ( (lighting < 0) || (lighting > F1_0 )) {
  1315.                     mprintf( (1, "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)));
  1316.                     Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting));
  1317.                 }
  1318.             } else if (!stricmp( arg, "strength" )) {
  1319.                 strength = fl2f(atof(equal_ptr));
  1320.             } else {
  1321.                 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
  1322.             }        
  1323.         } else {            // Must be a texture specification...
  1324.             load_polymodel_bitmap(arg);
  1325.         }
  1326.         arg = strtok( NULL, space );
  1327.     }
  1328.  
  1329.     if ( model_name_dead )
  1330.         n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num;
  1331.     else
  1332.         n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num;
  1333.  
  1334.     model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL);
  1335.  
  1336.     if (type == OL_CONTROL_CENTER)
  1337.         N_controlcen_guns = read_model_guns(model_name,controlcen_gun_points,controlcen_gun_dirs,NULL);
  1338.  
  1339.     if ( model_name_dead )
  1340.         Dead_modelnums[model_num]  = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL);
  1341.     else
  1342.         Dead_modelnums[model_num] = -1;
  1343.  
  1344.     if (type == -1)
  1345.         Error("No object type specfied for object in BITMAPS.TBL on line %d\n",linenum);
  1346.  
  1347.     ObjType[Num_total_object_types] = type;
  1348.     ObjId[Num_total_object_types] = model_num;
  1349.     ObjStrength[Num_total_object_types] = strength;
  1350.     
  1351.     //printf( "Object type %d is a control center\n", Num_total_object_types );
  1352.     Num_total_object_types++;
  1353.  
  1354.     if (type == OL_EXIT) {
  1355.         exit_modelnum = model_num;
  1356.         destroyed_exit_modelnum = Dead_modelnums[model_num];
  1357.     }
  1358.  
  1359. }
  1360.  
  1361. void bm_read_player_ship()
  1362. {
  1363.     char    *model_name_dying=NULL;
  1364.     char    *model_name[MAX_MODEL_VARIANTS];
  1365.     int    n_models=0,i;
  1366.     int    first_bitmap_num[MAX_MODEL_VARIANTS];
  1367.     char *equal_ptr;
  1368.     robot_info ri;
  1369.     int last_multi_bitmap_num=-1;
  1370.  
  1371.     // Process bitmaps 
  1372.     bm_flag = BM_NONE;
  1373.  
  1374.     arg = strtok( NULL, space ); 
  1375.  
  1376.     Player_ship->mass = Player_ship->drag = 0;    //stupid defaults
  1377.     Player_ship->expl_vclip_num = -1;
  1378.  
  1379.     while (arg!=NULL)    {
  1380.  
  1381.         equal_ptr = strchr( arg, '=' );
  1382.  
  1383.         if ( equal_ptr )    {
  1384.  
  1385.             *equal_ptr='\0';
  1386.             equal_ptr++;
  1387.  
  1388.             // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
  1389.  
  1390.             if (!stricmp( arg, "model" )) {
  1391.                 Assert(n_models==0);
  1392.                 model_name[0] = equal_ptr;
  1393.                 first_bitmap_num[0] = N_ObjBitmapPtrs;
  1394.                 n_models = 1;
  1395.             } else if (!stricmp( arg, "simple_model" )) {
  1396.                 model_name[n_models] = equal_ptr;
  1397.                 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
  1398.                 n_models++;
  1399.  
  1400.                 if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1)
  1401.                     last_multi_bitmap_num=N_ObjBitmapPtrs;
  1402.             }
  1403.             else if (!stricmp( arg, "mass" ))
  1404.                 Player_ship->mass = fl2f(atof(equal_ptr));
  1405.             else if (!stricmp( arg, "drag" ))
  1406.                 Player_ship->drag = fl2f(atof(equal_ptr));
  1407. //            else if (!stricmp( arg, "low_thrust" ))
  1408. //                Player_ship->low_thrust = fl2f(atof(equal_ptr));
  1409.             else if (!stricmp( arg, "max_thrust" ))
  1410.                 Player_ship->max_thrust = fl2f(atof(equal_ptr));
  1411.             else if (!stricmp( arg, "reverse_thrust" ))
  1412.                 Player_ship->reverse_thrust = fl2f(atof(equal_ptr));
  1413.             else if (!stricmp( arg, "brakes" ))
  1414.                 Player_ship->brakes = fl2f(atof(equal_ptr));
  1415.             else if (!stricmp( arg, "wiggle" ))
  1416.                 Player_ship->wiggle = fl2f(atof(equal_ptr));
  1417.             else if (!stricmp( arg, "max_rotthrust" ))
  1418.                 Player_ship->max_rotthrust = fl2f(atof(equal_ptr));
  1419.             else if (!stricmp( arg, "dying_pof" ))
  1420.                 model_name_dying = equal_ptr;
  1421.             else if (!stricmp( arg, "expl_vclip_num" ))
  1422.                 Player_ship->expl_vclip_num=atoi(equal_ptr);
  1423.             else {
  1424.                 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
  1425.             }        
  1426.         }
  1427.         else if (!stricmp( arg, "multi_textures" )) {
  1428.  
  1429.             First_multi_bitmap_num = N_ObjBitmapPtrs;
  1430.             first_bitmap_num[n_models] = N_ObjBitmapPtrs;
  1431.  
  1432.         }
  1433.         else            // Must be a texture specification...
  1434.  
  1435.             load_polymodel_bitmap(arg);
  1436.  
  1437.         arg = strtok( NULL, space );
  1438.     }
  1439.  
  1440.     Assert(model_name != NULL);
  1441.  
  1442.     if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1)
  1443.         last_multi_bitmap_num=N_ObjBitmapPtrs;
  1444.  
  1445.     if (First_multi_bitmap_num==-1)
  1446.         first_bitmap_num[n_models] = N_ObjBitmapPtrs;
  1447.  
  1448.     Assert(last_multi_bitmap_num-First_multi_bitmap_num == (MAX_NUM_NET_PLAYERS-1)*2);
  1449.  
  1450.     for (i=0;i<n_models;i++) {
  1451.         int n_textures;
  1452.         int model_num,last_model_num;
  1453.  
  1454.         n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
  1455.  
  1456.         model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],(i==0)?&ri:NULL);
  1457.  
  1458.         if (i==0)
  1459.             Player_ship->model_num = model_num;
  1460.         else
  1461.             Polygon_models[last_model_num].simpler_model = model_num+1;
  1462.  
  1463.         last_model_num = model_num;
  1464.     }
  1465.  
  1466.     if ( model_name_dying ) {
  1467.         Assert(n_models);
  1468.         Dying_modelnums[Player_ship->model_num]  = load_polygon_model(model_name_dying,first_bitmap_num[1]-first_bitmap_num[0],first_bitmap_num[0],NULL);
  1469.     }
  1470.  
  1471.     Assert(ri.n_guns == N_PLAYER_GUNS);
  1472.  
  1473.     //calc player gun positions
  1474.  
  1475.     {
  1476.         polymodel *pm;
  1477.         robot_info *r;
  1478.         vms_vector pnt;
  1479.         int mn;                //submodel number
  1480.         int gun_num;
  1481.     
  1482.         r = &ri;
  1483.         pm = &Polygon_models[Player_ship->model_num];
  1484.  
  1485.         for (gun_num=0;gun_num<r->n_guns;gun_num++) {
  1486.  
  1487.             pnt = r->gun_points[gun_num];
  1488.             mn = r->gun_submodels[gun_num];
  1489.         
  1490.             //instance up the tree for this gun
  1491.             while (mn != 0) {
  1492.                 vm_vec_add2(&pnt,&pm->submodel_offsets[mn]);
  1493.                 mn = pm->submodel_parents[mn];
  1494.             }
  1495.  
  1496.             Player_ship->gun_points[gun_num] = pnt;
  1497.         
  1498.         }
  1499.     }
  1500.  
  1501.  
  1502. }
  1503.  
  1504. void bm_read_some_file()
  1505. {
  1506.  
  1507.     switch (bm_flag) {
  1508.     case BM_COCKPIT:    {
  1509.         bitmap_index bitmap;
  1510.         bitmap = bm_load_sub(arg);
  1511.         Assert( Num_cockpits < N_COCKPIT_BITMAPS );
  1512.         cockpit_bitmap[Num_cockpits++] = bitmap;
  1513.  
  1514.         //bm_flag = BM_NONE;
  1515.         }
  1516.         break;
  1517.     case BM_GAUGES:
  1518.         bm_read_gauges();
  1519.         break;
  1520.     case BM_WEAPON:
  1521.         bm_read_weapon(0);
  1522.         break;
  1523.     case BM_VCLIP:
  1524.         bm_read_vclip();
  1525.         break;                    
  1526.     case BM_ECLIP:
  1527.         bm_read_eclip();
  1528.         break;
  1529.     case BM_TEXTURES:            {
  1530.         bitmap_index bitmap;
  1531.         bitmap = bm_load_sub(arg);
  1532.         Assert(tmap_count < MAX_TEXTURES);
  1533.           TmapList[tmap_count++] = texture_count;
  1534.         Textures[texture_count] = bitmap;
  1535.         set_texture_name( arg );
  1536.         Assert(texture_count < MAX_TEXTURES);
  1537.         texture_count++;
  1538.         NumTextures = texture_count;
  1539.         }
  1540.         break;
  1541.     case BM_WCLIP:
  1542.         bm_read_wclip();
  1543.         break;
  1544.     default:
  1545.         break;
  1546.     }
  1547. }
  1548.  
  1549. // ------------------------------------------------------------------------------
  1550. //    If unused_flag is set, then this is just a placeholder.  Don't actually reference vclips or load bbms.
  1551. void bm_read_weapon(int unused_flag)
  1552. {
  1553.     int    i,n;
  1554.     int    n_models=0;
  1555.     char     *equal_ptr;
  1556.     char    *pof_file_inner=NULL;
  1557.     char    *model_name[MAX_MODEL_VARIANTS];
  1558.     int    first_bitmap_num[MAX_MODEL_VARIANTS];
  1559.     int    lighted;                    //flag for whether is a texture is lighted
  1560.  
  1561.     Assert(N_weapon_types < MAX_WEAPON_TYPES);
  1562.  
  1563.     n = N_weapon_types;
  1564.     N_weapon_types++;
  1565.  
  1566.     if (unused_flag) {
  1567.         clear_to_end_of_line();
  1568.         return;
  1569.     }
  1570.  
  1571. #ifdef SHAREWARE
  1572.     if (Registered_only) {
  1573.         clear_to_end_of_line();
  1574.         return;
  1575.     }
  1576. #endif
  1577.  
  1578.     // Initialize weapon array
  1579.     Weapon_info[n].render_type = WEAPON_RENDER_NONE;        // 0=laser, 1=blob, 2=object
  1580.     Weapon_info[n].bitmap.index = 0;
  1581.     Weapon_info[n].model_num = -1;
  1582.     Weapon_info[n].model_num_inner = -1;
  1583.     Weapon_info[n].blob_size = 0x1000;                                    // size of blob
  1584.     Weapon_info[n].flash_vclip = -1;
  1585.     Weapon_info[n].flash_sound = SOUND_LASER_FIRED;
  1586.     Weapon_info[n].flash_size = 0;
  1587.     Weapon_info[n].robot_hit_vclip = -1;
  1588.     Weapon_info[n].robot_hit_sound = -1;
  1589.     Weapon_info[n].wall_hit_vclip = -1;
  1590.     Weapon_info[n].wall_hit_sound = -1;
  1591.     Weapon_info[n].impact_size = 0;
  1592.     for (i=0; i<NDL; i++) {
  1593.         Weapon_info[n].strength[i] = F1_0;
  1594.         Weapon_info[n].speed[i] = F1_0*10;
  1595.     }
  1596.     Weapon_info[n].mass = F1_0;
  1597.     Weapon_info[n].thrust = 0;
  1598.     Weapon_info[n].drag = 0;
  1599.     Weapon_info[n].persistent = 0;
  1600.  
  1601.     Weapon_info[n].energy_usage = 0;                    //    How much fuel is consumed to fire this weapon.
  1602.     Weapon_info[n].ammo_usage = 0;                    //    How many units of ammunition it uses.
  1603.     Weapon_info[n].fire_wait = F1_0/4;                //    Time until this weapon can be fired again.
  1604.     Weapon_info[n].fire_count = 1;                    //    Number of bursts fired from EACH GUN per firing.  For weapons which fire from both sides, 3*fire_count shots will be fired.
  1605.     Weapon_info[n].damage_radius = 0;                //    Radius of damage for missiles, not lasers.  Does damage to objects within this radius of hit point.
  1606. //--01/19/95, mk--    Weapon_info[n].damage_force = 0;                    //    Force (movement) due to explosion
  1607.     Weapon_info[n].destroyable = 1;                    //    Weapons default to destroyable
  1608.     Weapon_info[n].matter = 0;                            //    Weapons default to not being constructed of matter (they are energy!)
  1609.     Weapon_info[n].bounce = 0;                            //    Weapons default to not bouncing off walls
  1610.  
  1611.     Weapon_info[n].lifetime = WEAPON_DEFAULT_LIFETIME;                    //    Number of bursts fired from EACH GUN per firing.  For weapons which fire from both sides, 3*fire_count shots will be fired.
  1612.  
  1613.     Weapon_info[n].po_len_to_width_ratio = F1_0*10;
  1614.  
  1615.     Weapon_info[n].picture.index = 0;
  1616.     Weapon_info[n].homing_flag = 0;
  1617.  
  1618.     // Process arguments
  1619.     arg = strtok( NULL, space ); 
  1620.  
  1621.     lighted = 1;            //assume first texture is lighted
  1622.  
  1623.     while (arg!=NULL)    {
  1624.         equal_ptr = strchr( arg, '=' );
  1625.         if ( equal_ptr )    {
  1626.             *equal_ptr='\0';
  1627.             equal_ptr++;
  1628.             // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
  1629.             if (!stricmp( arg, "laser_bmp" ))    {
  1630.                 // Load bitmap with name equal_ptr
  1631.  
  1632.                 Weapon_info[n].bitmap = bm_load_sub(equal_ptr);        //load_polymodel_bitmap(equal_ptr);
  1633.                 Weapon_info[n].render_type = WEAPON_RENDER_LASER;
  1634.  
  1635.             } else if (!stricmp( arg, "blob_bmp" ))    {
  1636.                 // Load bitmap with name equal_ptr
  1637.  
  1638.                 Weapon_info[n].bitmap = bm_load_sub(equal_ptr);        //load_polymodel_bitmap(equal_ptr);
  1639.                 Weapon_info[n].render_type = WEAPON_RENDER_BLOB;
  1640.  
  1641.             } else if (!stricmp( arg, "weapon_vclip" ))    {
  1642.                 // Set vclip to play for this weapon.
  1643.                 Weapon_info[n].bitmap.index = 0;
  1644.                 Weapon_info[n].render_type = WEAPON_RENDER_VCLIP;
  1645.                 Weapon_info[n].weapon_vclip = atoi(equal_ptr);
  1646.  
  1647.             } else if (!stricmp( arg, "none_bmp" )) {
  1648.                 Weapon_info[n].bitmap = bm_load_sub(equal_ptr);
  1649.                 Weapon_info[n].render_type = WEAPON_RENDER_NONE;
  1650.  
  1651.             } else if (!stricmp( arg, "weapon_pof" ))    {
  1652.                 // Load pof file
  1653.                 Assert(n_models==0);
  1654.                 model_name[0] = equal_ptr;
  1655.                 first_bitmap_num[0] = N_ObjBitmapPtrs;
  1656.                 n_models=1;
  1657.             } else if (!stricmp( arg, "simple_model" )) {
  1658.                 model_name[n_models] = equal_ptr;
  1659.                 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
  1660.                 n_models++;
  1661.             } else if (!stricmp( arg, "weapon_pof_inner" ))    {
  1662.                 // Load pof file
  1663.                 pof_file_inner = equal_ptr;
  1664.             } else if (!stricmp( arg, "strength" )) {
  1665.                 for (i=0; i<NDL-1; i++) {
  1666.                     Weapon_info[n].strength[i] = i2f(atoi(equal_ptr));
  1667.                     equal_ptr = strtok(NULL, space);
  1668.                 }
  1669.                 Weapon_info[n].strength[i] = i2f(atoi(equal_ptr));
  1670.             } else if (!stricmp( arg, "mass" )) {
  1671.                 Weapon_info[n].mass = fl2f(atof(equal_ptr));
  1672.             } else if (!stricmp( arg, "drag" )) {
  1673.                 Weapon_info[n].drag = fl2f(atof(equal_ptr));
  1674.             } else if (!stricmp( arg, "thrust" )) {
  1675.                 Weapon_info[n].thrust = fl2f(atof(equal_ptr));
  1676.             } else if (!stricmp( arg, "matter" )) {
  1677.                 Weapon_info[n].matter = atoi(equal_ptr);
  1678.             } else if (!stricmp( arg, "bounce" )) {
  1679.                 Weapon_info[n].bounce = atoi(equal_ptr);
  1680.             } else if (!stricmp( arg, "speed" )) {
  1681.                 for (i=0; i<NDL-1; i++) {
  1682.                     Weapon_info[n].speed[i] = i2f(atoi(equal_ptr));
  1683.                     equal_ptr = strtok(NULL, space);
  1684.                 }
  1685.                 Weapon_info[n].speed[i] = i2f(atoi(equal_ptr));
  1686.             } else if (!stricmp( arg, "flash_vclip" ))    {
  1687.                 Weapon_info[n].flash_vclip = atoi(equal_ptr);
  1688.             } else if (!stricmp( arg, "flash_sound" ))    {
  1689.                 Weapon_info[n].flash_sound = atoi(equal_ptr);
  1690.             } else if (!stricmp( arg, "flash_size" ))    {
  1691.                 Weapon_info[n].flash_size = fl2f(atof(equal_ptr));
  1692.             } else if (!stricmp( arg, "blob_size" ))    {
  1693.                 Weapon_info[n].blob_size = fl2f(atof(equal_ptr));
  1694.             } else if (!stricmp( arg, "robot_hit_vclip" ))    {
  1695.                 Weapon_info[n].robot_hit_vclip = atoi(equal_ptr);
  1696.             } else if (!stricmp( arg, "robot_hit_sound" ))    {
  1697.                 Weapon_info[n].robot_hit_sound = atoi(equal_ptr);
  1698.             } else if (!stricmp( arg, "wall_hit_vclip" ))    {
  1699.                 Weapon_info[n].wall_hit_vclip = atoi(equal_ptr);
  1700.             } else if (!stricmp( arg, "wall_hit_sound" ))    {
  1701.                 Weapon_info[n].wall_hit_sound = atoi(equal_ptr);
  1702.             } else if (!stricmp( arg, "impact_size" ))    {
  1703.                 Weapon_info[n].impact_size = fl2f(atof(equal_ptr));
  1704.             } else if (!stricmp( arg, "lighted" ))    {
  1705.                 lighted = atoi(equal_ptr);
  1706.             } else if (!stricmp( arg, "lw_ratio" ))    {
  1707.                 Weapon_info[n].po_len_to_width_ratio = fl2f(atof(equal_ptr));
  1708.             } else if (!stricmp( arg, "lightcast" ))    {
  1709.                 Weapon_info[n].light = fl2f(atof(equal_ptr));
  1710.             } else if (!stricmp( arg, "persistent" ))    {
  1711.                 Weapon_info[n].persistent = atoi(equal_ptr);
  1712.             } else if (!stricmp(arg, "energy_usage" )) {
  1713.                 Weapon_info[n].energy_usage = fl2f(atof(equal_ptr));
  1714.             } else if (!stricmp(arg, "ammo_usage" )) {
  1715.                 Weapon_info[n].ammo_usage = atoi(equal_ptr);
  1716.             } else if (!stricmp(arg, "fire_wait" )) {
  1717.                 Weapon_info[n].fire_wait = fl2f(atof(equal_ptr));
  1718.             } else if (!stricmp(arg, "fire_count" )) {
  1719.                 Weapon_info[n].fire_count = atoi(equal_ptr);
  1720.             } else if (!stricmp(arg, "damage_radius" )) {
  1721.                 Weapon_info[n].damage_radius = fl2f(atof(equal_ptr));
  1722. //--01/19/95, mk--            } else if (!stricmp(arg, "damage_force" )) {
  1723. //--01/19/95, mk--                Weapon_info[n].damage_force = fl2f(atof(equal_ptr));
  1724.             } else if (!stricmp(arg, "lifetime" )) {
  1725.                 Weapon_info[n].lifetime = fl2f(atof(equal_ptr));
  1726.             } else if (!stricmp(arg, "destroyable" )) {
  1727.                 Weapon_info[n].destroyable = atoi(equal_ptr);
  1728.             } else if (!stricmp(arg, "picture" )) {
  1729.                 Weapon_info[n].picture = bm_load_sub(equal_ptr);
  1730.             } else if (!stricmp(arg, "homing" )) {
  1731.                 Weapon_info[n].homing_flag = !!atoi(equal_ptr);
  1732.             } else {
  1733.                 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
  1734.             }        
  1735.         } else {            // Must be a texture specification...
  1736.             grs_bitmap *bm;
  1737.  
  1738.             bm = load_polymodel_bitmap(arg);
  1739.             if (! lighted)
  1740.                 bm->bm_flags |= BM_FLAG_NO_LIGHTING;
  1741.  
  1742.             lighted = 1;            //default for next bitmap is lighted
  1743.         }
  1744.         arg = strtok( NULL, space );
  1745.     }
  1746.  
  1747.     first_bitmap_num[n_models] = N_ObjBitmapPtrs;
  1748.  
  1749.     for (i=0;i<n_models;i++) {
  1750.         int n_textures;
  1751.         int model_num,last_model_num;
  1752.  
  1753.         n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
  1754.  
  1755.         model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],NULL);
  1756.  
  1757.         if (i==0) {
  1758.             Weapon_info[n].render_type = WEAPON_RENDER_POLYMODEL;
  1759.             Weapon_info[n].model_num = model_num;
  1760.         }
  1761.         else
  1762.             Polygon_models[last_model_num].simpler_model = model_num+1;
  1763.  
  1764.         last_model_num = model_num;
  1765.     }
  1766.  
  1767.     if ( pof_file_inner )    {
  1768.         Assert(n_models);
  1769.         Weapon_info[n].model_num_inner = load_polygon_model(pof_file_inner,first_bitmap_num[1]-first_bitmap_num[0],first_bitmap_num[0],NULL);
  1770.     }
  1771.  
  1772.     if ((Weapon_info[n].ammo_usage == 0) && (Weapon_info[n].energy_usage == 0))
  1773.         mprintf((1, "Warning: Weapon %i has ammo and energy usage of 0.\n", n));
  1774.  
  1775. // -- render type of none is now legal --    Assert( Weapon_info[n].render_type != WEAPON_RENDER_NONE );
  1776. }
  1777.  
  1778.  
  1779.  
  1780.  
  1781.  
  1782. // ------------------------------------------------------------------------------
  1783. #define DEFAULT_POWERUP_SIZE i2f(3)
  1784.  
  1785. void bm_read_powerup(int unused_flag)
  1786. {
  1787.     int n;
  1788.     char     *equal_ptr;
  1789.  
  1790.     Assert(N_powerup_types < MAX_POWERUP_TYPES);
  1791.  
  1792.     n = N_powerup_types;
  1793.     N_powerup_types++;
  1794.  
  1795.     if (unused_flag) {
  1796.         clear_to_end_of_line();
  1797.         return;
  1798.     }
  1799.  
  1800.     // Initialize powerup array
  1801.     Powerup_info[n].light = F1_0/3;        //    Default lighting value.
  1802.     Powerup_info[n].vclip_num = -1;
  1803.     Powerup_info[n].hit_sound = -1;
  1804.     Powerup_info[n].size = DEFAULT_POWERUP_SIZE;
  1805.     Powerup_names[n][0] = 0;
  1806.  
  1807.     // Process arguments
  1808.     arg = strtok( NULL, space ); 
  1809.  
  1810.     while (arg!=NULL)    {
  1811.         equal_ptr = strchr( arg, '=' );
  1812.         if ( equal_ptr )    {
  1813.             *equal_ptr='\0';
  1814.             equal_ptr++;
  1815.             // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
  1816.             if (!stricmp( arg, "vclip_num" ))    {
  1817.                 Powerup_info[n].vclip_num = atoi(equal_ptr);
  1818.             } else if (!stricmp( arg, "light" ))    {
  1819.                 Powerup_info[n].light = fl2f(atof(equal_ptr));
  1820.             } else if (!stricmp( arg, "hit_sound" ))    {
  1821.                 Powerup_info[n].hit_sound = atoi(equal_ptr);
  1822.             } else if (!stricmp( arg, "name" )) {
  1823.                 Assert(strlen(equal_ptr) < POWERUP_NAME_LENGTH);    //    Oops, name too long.
  1824.                 strcpy(Powerup_names[n], &equal_ptr[1]);
  1825.                 Powerup_names[n][strlen(Powerup_names[n])-1] = 0;
  1826.             } else if (!stricmp( arg, "size" ))    {
  1827.                 Powerup_info[n].size = fl2f(atof(equal_ptr));
  1828.             } else {
  1829.                 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
  1830.             }        
  1831.         } else {            // Must be a texture specification...
  1832.             mprintf( (1, "Invalid argument, %s in bitmaps.tbl\n", arg ));
  1833.         }
  1834.         arg = strtok( NULL, space );
  1835.     }
  1836.  
  1837.     ObjType[Num_total_object_types] = OL_POWERUP;
  1838.     ObjId[Num_total_object_types] = n;
  1839.     //printf( "Object type %d is a powerup\n", Num_total_object_types );
  1840.     Num_total_object_types++;
  1841.  
  1842. }
  1843.  
  1844. void bm_read_hostage()    
  1845. {
  1846.     int n;
  1847.     char     *equal_ptr;
  1848.  
  1849.     Assert(N_hostage_types < MAX_HOSTAGE_TYPES);
  1850.  
  1851.     n = N_hostage_types;
  1852.     N_hostage_types++;
  1853.  
  1854.     // Process arguments
  1855.     arg = strtok( NULL, space ); 
  1856.  
  1857.     while (arg!=NULL)    {
  1858.         equal_ptr = strchr( arg, '=' );
  1859.         if ( equal_ptr )    {
  1860.             *equal_ptr='\0';
  1861.             equal_ptr++;
  1862.  
  1863.             if (!stricmp( arg, "vclip_num" ))
  1864.  
  1865.                 Hostage_vclip_num[n] = atoi(equal_ptr);
  1866.  
  1867.             else
  1868.  
  1869.                 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
  1870.  
  1871.         } else
  1872.             mprintf( (1, "Invalid argument, %s in bitmaps.tbl at line %d\n", arg, linenum ));
  1873.  
  1874.         arg = strtok( NULL, space );
  1875.     }
  1876.  
  1877.     ObjType[Num_total_object_types] = OL_HOSTAGE;
  1878.     ObjId[Num_total_object_types] = n;
  1879.     //printf( "Object type %d is a hostage\n", Num_total_object_types );
  1880.     Num_total_object_types++;
  1881.  
  1882. }
  1883.  
  1884.  
  1885. void bm_read_hostage_face()    
  1886. {
  1887.     char *abm_name,*equal_ptr;
  1888.     int clip_num=-1,sound_num=-1;
  1889.     fix time;
  1890.  
  1891.     abm_name = strtok( NULL, space );
  1892.  
  1893.     arg = strtok( NULL, space ); 
  1894.     while (arg!=NULL)    {
  1895.         equal_ptr = strchr( arg, '=' );
  1896.         if ( equal_ptr )    {
  1897.             *equal_ptr='\0';
  1898.             equal_ptr++;
  1899.  
  1900.             // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
  1901.  
  1902.             if (!stricmp( arg, "clip_num" ))    {
  1903.                 clip_num = atoi(equal_ptr);
  1904.             } else if (!stricmp( arg, "time" ))    {
  1905.                 time = fl2f(atof(equal_ptr));
  1906.             } else if (!stricmp( arg, "sound_num" ))    {
  1907.                 sound_num = atoi(equal_ptr);
  1908.             }
  1909.         }
  1910.  
  1911.         arg = strtok( NULL, space );
  1912.     }
  1913.  
  1914.  #ifndef SHAREWARE
  1915.  
  1916.     Assert(clip_num>=0 && clip_num<MAX_HOSTAGES);
  1917.  
  1918.     ab_load( abm_name, Hostage_face_clip[clip_num].frames, &Hostage_face_clip[clip_num].num_frames );
  1919.  
  1920.     Assert(Hostage_face_clip[clip_num].num_frames < MAX_BITMAPS_PER_BRUSH);
  1921.  
  1922.     Hostage_face_clip[clip_num].play_time = time;
  1923.     Hostage_face_clip[clip_num].sound_num = sound_num;
  1924.     Hostage_face_clip[clip_num].frame_time = time/Hostage_face_clip[clip_num].num_frames;
  1925.  
  1926.  #endif
  1927. }
  1928.  
  1929. void bm_write_all(FILE *fp)
  1930. {
  1931.     int i;
  1932.  
  1933.     fwrite( &NumTextures, sizeof(int), 1, fp );
  1934.     fwrite( Textures, sizeof(bitmap_index), MAX_TEXTURES, fp );
  1935.     fwrite( TmapInfo, sizeof(tmap_info), MAX_TEXTURES, fp );
  1936.  
  1937.     fwrite( Sounds, sizeof(ubyte), MAX_SOUNDS, fp );
  1938.     fwrite( AltSounds, sizeof(ubyte), MAX_SOUNDS, fp );
  1939.  
  1940.     fwrite( &Num_vclips, sizeof(int), 1, fp );
  1941.     fwrite( Vclip, sizeof(vclip), VCLIP_MAXNUM, fp );
  1942.  
  1943.     fwrite( &Num_effects, sizeof(int), 1, fp );
  1944.     fwrite( Effects, sizeof(eclip), MAX_EFFECTS, fp );
  1945.  
  1946.     fwrite( &Num_wall_anims, sizeof(int), 1, fp );
  1947.     fwrite( WallAnims, sizeof(wclip), MAX_WALL_ANIMS, fp );
  1948.  
  1949.     fwrite( &N_robot_types, sizeof(int), 1, fp );
  1950.     fwrite( Robot_info, sizeof(robot_info), MAX_ROBOT_TYPES, fp );
  1951.  
  1952.     fwrite( &N_robot_joints, sizeof(int), 1, fp );
  1953.     fwrite( Robot_joints, sizeof(jointpos), MAX_ROBOT_JOINTS, fp );
  1954.  
  1955.     fwrite( &N_weapon_types, sizeof(int), 1, fp );
  1956.     fwrite( Weapon_info, sizeof(weapon_info), MAX_WEAPON_TYPES, fp );
  1957.  
  1958.     fwrite( &N_powerup_types, sizeof(int), 1, fp );
  1959.     fwrite( Powerup_info, sizeof(powerup_type_info), MAX_POWERUP_TYPES, fp );
  1960.     
  1961.     fwrite( &N_polygon_models, sizeof(int), 1, fp );
  1962.     fwrite( Polygon_models, sizeof(polymodel), N_polygon_models, fp );
  1963.  
  1964.     for (i=0; i<N_polygon_models; i++ )    {
  1965.         fwrite( Polygon_models[i].model_data, sizeof(ubyte), Polygon_models[i].model_data_size, fp );
  1966.     }
  1967.  
  1968.     fwrite( Gauges, sizeof(bitmap_index), MAX_GAUGE_BMS, fp );
  1969.  
  1970.     fwrite( Dying_modelnums, sizeof(int), MAX_POLYGON_MODELS, fp );
  1971.     fwrite( Dead_modelnums, sizeof(int), MAX_POLYGON_MODELS, fp );
  1972.  
  1973.     fwrite( ObjBitmaps, sizeof(bitmap_index), MAX_OBJ_BITMAPS, fp );
  1974.     fwrite( ObjBitmapPtrs, sizeof(ushort), MAX_OBJ_BITMAPS, fp );
  1975.  
  1976.     fwrite( &only_player_ship, sizeof(player_ship), 1, fp );
  1977.  
  1978.     fwrite( &Num_cockpits, sizeof(int), 1, fp );
  1979.     fwrite( cockpit_bitmap, sizeof(bitmap_index), N_COCKPIT_BITMAPS, fp );
  1980.  
  1981.     fwrite( Sounds, sizeof(ubyte), MAX_SOUNDS, fp );
  1982.     fwrite( AltSounds, sizeof(ubyte), MAX_SOUNDS, fp );
  1983.  
  1984.     fwrite( &Num_total_object_types, sizeof(int), 1, fp );
  1985.     fwrite( ObjType, sizeof(byte), MAX_OBJTYPE, fp );
  1986.     fwrite( ObjId, sizeof(byte), MAX_OBJTYPE, fp );
  1987.     fwrite( ObjStrength, sizeof(fix), MAX_OBJTYPE, fp );
  1988.  
  1989.     fwrite( &First_multi_bitmap_num, sizeof(int), 1, fp );
  1990.  
  1991.     fwrite( &N_controlcen_guns, sizeof(int), 1, fp );
  1992.     fwrite( controlcen_gun_points, sizeof(vms_vector), MAX_CONTROLCEN_GUNS, fp );
  1993.     fwrite( controlcen_gun_dirs, sizeof(vms_vector), MAX_CONTROLCEN_GUNS, fp );
  1994.     fwrite( &exit_modelnum, sizeof(int), 1, fp );
  1995.     fwrite( &destroyed_exit_modelnum, sizeof(int), 1, fp );
  1996. }
  1997.  
  1998. #endif
  1999. 
  2000.