1 /* $Id: bmread.c,v 1.5 2003-10-10 09:36:34 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Routines to parse bitmaps.tbl
20 * Revision 2.4 1995/03/28 18:05:29 john
21 * Fixed it so you don't have to delete pig after changing bitmaps.tbl
23 * Revision 2.3 1995/03/07 16:52:03 john
24 * Fixed robots not moving without edtiro bug.
26 * Revision 2.2 1995/03/06 16:10:20 mike
27 * Fix compile errors if building without editor.
29 * Revision 2.1 1995/03/02 14:55:40 john
30 * Fixed bug with EDITOR never defined.
32 * Revision 2.0 1995/02/27 11:33:10 john
33 * New version 2.0, which has no anonymous unions, builds with
34 * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
36 * Revision 1.1 1995/02/25 14:02:36 john
90 #include "editor/texpage.h"
102 #define BM_WALL_ANIMS 12
106 #define BM_GAUGES_HIRES 21
108 #define MAX_BITMAPS_PER_BRUSH 30
110 extern player_ship only_player_ship; // In bm.c
112 short N_ObjBitmaps=0;
113 short N_ObjBitmapPtrs=0;
114 static int Num_robot_ais = 0;
115 int TmapList[MAX_TEXTURES];
116 char Powerup_names[MAX_POWERUP_TYPES][POWERUP_NAME_LENGTH];
117 char Robot_names[MAX_ROBOT_TYPES][ROBOT_NAME_LENGTH];
119 //---------------- Internal variables ---------------------------
120 static int Registered_only = 0; // Gets set by ! in column 1.
121 static int SuperX = -1;
122 static int Installed=0;
124 static short tmap_count = 0;
125 static short texture_count = 0;
126 static short clip_count = 0;
127 static short clip_num;
128 static short sound_num;
131 static int hit_sound = -1;
132 static sbyte bm_flag = BM_NONE;
133 static int abm_flag = 0;
134 static int rod_flag = 0;
135 static short wall_open_sound, wall_close_sound,wall_explodes,wall_blastable, wall_hidden;
137 static int obj_eclip;
138 static char *dest_bm; //clip number to play when destroyed
139 static int dest_vclip; //what vclip to play when exploding
140 static int dest_eclip; //what eclip to play when exploding
141 static fix dest_size; //3d size of explosion
142 static int crit_clip; //clip number to play when destroyed
143 static int crit_flag; //flag if this is a destroyed eclip
144 static int tmap1_flag; //flag if this is used as tmap_num (not tmap_num2)
145 static int num_sounds=0;
147 int linenum; //line int table currently being parsed
149 //------------------- Useful macros and variables ---------------
150 #define REMOVE_EOL(s) remove_char((s),'\n')
151 #define REMOVE_COMMENTS(s) remove_char((s),';')
152 #define REMOVE_DOTS(s) remove_char((s),'.')
154 #define IFTOK(str) if (!strcmp(arg, str))
155 char *space = { " \t" };
156 //--unused-- char *equal = { "=" };
157 char *equal_space = { " \t=" };
160 // For the sake of LINT, defining prototypes to module's functions
161 void bm_read_alias(void);
162 void bm_read_marker(void);
163 void bm_read_robot_ai(void);
164 void bm_read_powerup(int unused_flag);
165 void bm_read_hostage(void);
166 void bm_read_robot(void);
167 void bm_read_weapon(int unused_flag);
168 void bm_read_reactor(void);
169 void bm_read_exitmodel(void);
170 void bm_read_player_ship(void);
171 void bm_read_some_file(void);
172 void bm_read_sound(void);
173 void bm_write_extra_robots(void);
174 void clear_to_end_of_line(void);
175 void verify_textures(void);
178 //----------------------------------------------------------------------
179 void remove_char( char * s, char c )
186 //---------------------------------------------------------------
187 int compute_average_pixel(grs_bitmap *new)
189 int row, column, color;
191 int total_red, total_green, total_blue;
193 pptr = (char *)new->bm_data;
199 for (row=0; row<new->bm_h; row++)
200 for (column=0; column<new->bm_w; column++) {
202 total_red += gr_palette[color*3];
203 total_green += gr_palette[color*3+1];
204 total_blue += gr_palette[color*3+2];
207 total_red /= (new->bm_h * new->bm_w);
208 total_green /= (new->bm_h * new->bm_w);
209 total_blue /= (new->bm_h * new->bm_w);
211 return BM_XRGB(total_red/2, total_green/2, total_blue/2);
214 //---------------------------------------------------------------
215 // Loads a bitmap from either the piggy file, a r64 file, or a
216 // whatever extension is passed.
218 bitmap_index bm_load_sub( char * filename )
220 bitmap_index bitmap_num;
223 int iff_error; //reference parm to avoid warning message
226 bitmap_num.index = 0;
229 if (Registered_only) {
230 //mprintf( 0, "Skipping registered-only bitmap '%s'\n", filename );
235 _splitpath( filename, NULL, NULL, fname, NULL );
237 bitmap_num=piggy_find_bitmap( fname );
238 if (bitmap_num.index) {
239 //mprintf(( 0, "Found bitmap '%s' in pig!\n", fname ));
243 MALLOC( new, grs_bitmap, 1 );
244 iff_error = iff_read_bitmap(filename,new,BM_LINEAR,newpal);
246 if (iff_error != IFF_NO_ERROR) {
247 mprintf((1, "File %s - IFF error: %s",filename,iff_errormsg(iff_error)));
248 Error("File <%s> - IFF error: %s, line %d",filename,iff_errormsg(iff_error),linenum);
251 if ( iff_has_transparency )
252 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
254 gr_remap_bitmap_good( new, newpal, -1, SuperX );
256 new->avg_color = compute_average_pixel(new);
258 // -- mprintf((0, "N" ));
259 bitmap_num = piggy_register_bitmap( new, fname, 0 );
264 extern grs_bitmap bogus_bitmap;
265 extern ubyte bogus_bitmap_initialized;
266 extern digi_sound bogus_sound;
268 void ab_load( char * filename, bitmap_index bmp[], int *nframes )
270 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
273 int iff_error; //reference parm to avoid warning message
279 if (Registered_only) {
280 Assert( bogus_bitmap_initialized != 0 );
281 mprintf(( 0, "Skipping registered-only animation '%s'\n", filename ));
282 bmp[0].index = 0; //index of bogus bitmap==0 (I think) //&bogus_bitmap;
289 _splitpath( filename, NULL, NULL, fname, NULL );
291 for (i=0; i<MAX_BITMAPS_PER_BRUSH; i++ ) {
292 sprintf( tempname, "%s#%d", fname, i );
293 bi = piggy_find_bitmap( tempname );
297 //mprintf(( 0, "Found animation frame %d, %s, in piggy file\n", i, tempname ));
305 // Note that last argument passes an address to the array newpal (which is a pointer).
306 // type mismatch found using lint, will substitute this line with an adjusted
307 // one. If fatal error, then it can be easily changed.
308 // iff_error = iff_read_animbrush(filename,bm,MAX_BITMAPS_PER_BRUSH,nframes,&newpal);
309 iff_error = iff_read_animbrush(filename,bm,MAX_BITMAPS_PER_BRUSH,nframes,newpal);
310 if (iff_error != IFF_NO_ERROR) {
311 mprintf((1,"File %s - IFF error: %s",filename,iff_errormsg(iff_error)));
312 Error("File <%s> - IFF error: %s, line %d",filename,iff_errormsg(iff_error),linenum);
315 for (i=0;i< *nframes; i++) {
316 bitmap_index new_bmp;
317 sprintf( tempname, "%s#%d", fname, i );
318 if ( iff_has_transparency )
319 gr_remap_bitmap_good( bm[i], newpal, iff_transparent_color, SuperX );
321 gr_remap_bitmap_good( bm[i], newpal, -1, SuperX );
323 bm[i]->avg_color = compute_average_pixel(bm[i]);
325 new_bmp = piggy_register_bitmap( bm[i], tempname, 0 );
329 mprintf((0, "Registering %s in piggy file.", tempname ));
336 int ds_load( char * filename ) {
344 if (Registered_only) {
345 //mprintf( 0, "Skipping registered-only sound '%s'\n", filename );
346 return 0; //don't know what I should return here //&bogus_sound;
350 _splitpath( filename, NULL, NULL, fname, NULL );
351 _makepath( rawname, NULL, NULL,fname, (digi_sample_rate==SAMPLE_RATE_22K)?".R22":".RAW" );
353 i=piggy_find_sound( fname );
358 cfp = cfopen( rawname, "rb" );
361 new.length = cfilelength( cfp );
362 MALLOC( new.data, ubyte, new.length );
363 cfread( new.data, 1, new.length, cfp );
365 // -- mprintf( (0, "S" ));
366 // -- mprintf( (0, "<%s>", rawname ));
368 mprintf( (1, "Warning: Couldn't find '%s'\n", filename ));
371 i = piggy_register_sound( &new, fname, 0 );
380 xarg = strtok( NULL, space );
389 xarg = strtok( NULL, space );
393 // rotates a byte left one bit, preserving the bit falling off the right
395 //rotate_left(char *c)
407 //loads a texture and returns the texture num
408 int get_texture(char *name)
410 char short_name[FILENAME_LEN];
413 strcpy(short_name,name);
414 REMOVE_DOTS(short_name);
415 for (i=0;i<texture_count;i++)
416 if (!stricmp(TmapInfo[i].filename,short_name))
418 if (i==texture_count) {
419 Textures[texture_count] = bm_load_sub(name);
420 strcpy( TmapInfo[texture_count].filename, short_name);
422 Assert(texture_count < MAX_TEXTURES);
423 NumTextures = texture_count;
429 #define LINEBUF_SIZE 600
431 #define DEFAULT_PIG_PALETTE "groupa.256"
433 //-----------------------------------------------------------------
434 // Initializes all bitmaps from BITMAPS.TBL file.
435 // This is called when the editor is IN.
436 // If no editor, bm_init() is called.
437 int bm_init_use_tbl()
440 char inputline[LINEBUF_SIZE];
443 gr_use_palette_table(DEFAULT_PIG_PALETTE);
445 load_palette(DEFAULT_PIG_PALETTE,-2,0); //special: tell palette code which pig is loaded
447 init_polygon_models();
449 ObjType[0] = OL_PLAYER;
451 Num_total_object_types = 1;
453 for (i=0; i<MAX_SOUNDS; i++ ) {
458 for (i=0; i<MAX_TEXTURES; i++ ) {
459 TmapInfo[i].eclip_num = -1;
460 TmapInfo[i].flags = 0;
461 TmapInfo[i].slide_u = TmapInfo[i].slide_v = 0;
462 TmapInfo[i].destroyed = -1;
465 for (i=0;i<MAX_REACTORS;i++)
466 Reactors[i].model_num = -1;
469 for (i=0; i<MAX_EFFECTS; i++ ) {
470 //Effects[i].bm_ptr = (grs_bitmap **) -1;
471 Effects[i].changing_wall_texture = -1;
472 Effects[i].changing_object_texture = -1;
473 Effects[i].segnum = -1;
474 Effects[i].vc.num_frames = -1; //another mark of being unused
477 for (i=0;i<MAX_POLYGON_MODELS;i++)
478 Dying_modelnums[i] = Dead_modelnums[i] = -1;
481 for (i=0; i<VCLIP_MAXNUM; i++ ) {
482 Vclip[i].num_frames = -1;
486 for (i=0; i<MAX_WALL_ANIMS; i++ )
487 WallAnims[i].num_frames = -1;
490 setbuf(stdout, NULL); // unbuffered output via printf
497 piggy_init(); //don't care about error, since no pig is ok for editor
499 // if ( FindArg( "-nobm" ) ) {
500 // piggy_read_sounds();
504 // Open BITMAPS.TBL for reading.
506 InfoFile = cfopen( "BITMAPS.TBL", "rb" );
507 if (InfoFile == NULL) {
508 InfoFile = cfopen("BITMAPS.BIN", "rb");
509 if (InfoFile == NULL)
510 Error("Missing BITMAPS.TBL and BITMAPS.BIN file\n");
515 cfseek( InfoFile, 0L, SEEK_SET);
517 while (cfgets(inputline, LINEBUF_SIZE, InfoFile)) {
523 if (inputline[0]==' ' || inputline[0]=='\t') {
525 for (t=inputline;*t && *t!='\n';t++)
526 if (! (*t==' ' || *t=='\t')) {
527 mprintf((1,"Suspicious: line %d of BITMAPS.TBL starts with whitespace\n",linenum));
532 if (have_bin_tbl) { // is this a binary tbl file
533 for (i = 0; i < strlen(inputline) - 1; i++) {
534 encode_rotate_left(&(inputline[i]));
535 inputline[i] = inputline[i] ^ BITMAP_TBL_XOR;
536 encode_rotate_left(&(inputline[i]));
539 while (inputline[(l=strlen(inputline))-2]=='\\') {
540 if (!isspace(inputline[l-3])) { //if not space before backslash...
541 inputline[l-2] = ' '; //add one
544 cfgets(inputline+l-2,LINEBUF_SIZE-(l-2), InfoFile);
549 REMOVE_EOL(inputline);
550 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
552 if (strlen(inputline) == LINEBUF_SIZE-1)
553 Error("Possible line truncation in BITMAPS.TBL on line %d\n",linenum);
557 if ( (temp_ptr=strstr( inputline, "superx=" )) ) {
558 SuperX = atoi( &temp_ptr[7] );
559 Assert(SuperX == 254);
560 //the superx color isn't kept around, so the new piggy regeneration
561 //code doesn't know what it is, so it assumes that it's 254, so
562 //this code requires that it be 254
566 arg = strtok( inputline, space );
575 // Check all possible flags and defines.
576 if (*arg == '$') bm_flag = BM_NONE; // reset to no flags as default.
578 IFTOK("$COCKPIT") bm_flag = BM_COCKPIT;
579 else IFTOK("$GAUGES") {bm_flag = BM_GAUGES; clip_count = 0;}
580 else IFTOK("$GAUGES_HIRES"){bm_flag = BM_GAUGES_HIRES; clip_count = 0;}
581 else IFTOK("$SOUND") bm_read_sound();
582 else IFTOK("$DOOR_ANIMS") bm_flag = BM_WALL_ANIMS;
583 else IFTOK("$WALL_ANIMS") bm_flag = BM_WALL_ANIMS;
584 else IFTOK("$TEXTURES") bm_flag = BM_TEXTURES;
585 else IFTOK("$VCLIP") {bm_flag = BM_VCLIP; vlighting = 0; clip_count = 0;}
586 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;}
587 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;}
589 else IFTOK("$EFFECTS") {bm_flag = BM_EFFECTS; clip_num = 0;}
590 else IFTOK("$ALIAS") bm_read_alias();
593 else IFTOK("!METALS_FLAG") TextureMetals = texture_count;
594 else IFTOK("!LIGHTS_FLAG") TextureLights = texture_count;
595 else IFTOK("!EFFECTS_FLAG") TextureEffects = texture_count;
598 else IFTOK("lighting") TmapInfo[texture_count-1].lighting = fl2f(get_float());
599 else IFTOK("damage") TmapInfo[texture_count-1].damage = fl2f(get_float());
600 else IFTOK("volatile") TmapInfo[texture_count-1].flags |= TMI_VOLATILE;
601 else IFTOK("goal_blue") TmapInfo[texture_count-1].flags |= TMI_GOAL_BLUE;
602 else IFTOK("goal_red") TmapInfo[texture_count-1].flags |= TMI_GOAL_RED;
603 else IFTOK("water") TmapInfo[texture_count-1].flags |= TMI_WATER;
604 else IFTOK("force_field") TmapInfo[texture_count-1].flags |= TMI_FORCE_FIELD;
605 else IFTOK("slide") {TmapInfo[texture_count-1].slide_u = fl2f(get_float())>>8; TmapInfo[texture_count-1].slide_v = fl2f(get_float())>>8;}
606 else IFTOK("destroyed") {int t=texture_count-1; TmapInfo[t].destroyed = get_texture(strtok( NULL, space ));}
607 //else IFTOK("Num_effects") Num_effects = get_int();
608 else IFTOK("Num_wall_anims") Num_wall_anims = get_int();
609 else IFTOK("clip_num") clip_num = get_int();
610 else IFTOK("dest_bm") dest_bm = strtok( NULL, space );
611 else IFTOK("dest_vclip") dest_vclip = get_int();
612 else IFTOK("dest_eclip") dest_eclip = get_int();
613 else IFTOK("dest_size") dest_size = fl2f(get_float());
614 else IFTOK("crit_clip") crit_clip = get_int();
615 else IFTOK("crit_flag") crit_flag = get_int();
616 else IFTOK("sound_num") sound_num = get_int();
617 else IFTOK("frames") frames = get_int();
618 else IFTOK("time") time = get_float();
619 else IFTOK("obj_eclip") obj_eclip = get_int();
620 else IFTOK("hit_sound") hit_sound = get_int();
621 else IFTOK("abm_flag") abm_flag = get_int();
622 else IFTOK("tmap1_flag") tmap1_flag = get_int();
623 else IFTOK("vlighting") vlighting = get_float();
624 else IFTOK("rod_flag") rod_flag = get_int();
625 else IFTOK("superx") get_int();
626 else IFTOK("open_sound") wall_open_sound = get_int();
627 else IFTOK("close_sound") wall_close_sound = get_int();
628 else IFTOK("explodes") wall_explodes = get_int();
629 else IFTOK("blastable") wall_blastable = get_int();
630 else IFTOK("hidden") wall_hidden = get_int();
631 else IFTOK("$ROBOT_AI") bm_read_robot_ai();
633 else IFTOK("$POWERUP") {bm_read_powerup(0); continue;}
634 else IFTOK("$POWERUP_UNUSED") {bm_read_powerup(1); continue;}
635 else IFTOK("$HOSTAGE") {bm_read_hostage(); continue;}
636 else IFTOK("$ROBOT") {bm_read_robot(); continue;}
637 else IFTOK("$WEAPON") {bm_read_weapon(0); continue;}
638 else IFTOK("$WEAPON_UNUSED") {bm_read_weapon(1); continue;}
639 else IFTOK("$REACTOR") {bm_read_reactor(); continue;}
640 else IFTOK("$MARKER") {bm_read_marker(); continue;}
641 else IFTOK("$PLAYER_SHIP") {bm_read_player_ship(); continue;}
642 else IFTOK("$EXIT") {
646 clear_to_end_of_line();
650 else { //not a special token, must be a bitmap!
652 // Remove any illegal/unwanted spaces and tabs at this point.
653 while ((*arg=='\t') || (*arg==' ')) arg++;
654 if (*arg == '\0') { break; }
656 //check for '=' in token, indicating error
658 Error("Unknown token <'%s'> on line %d of BITMAPS.TBL",arg,linenum);
660 // Otherwise, 'arg' is apparently a bitmap filename.
661 // Load bitmap and process it below:
666 arg = strtok( NULL, equal_space );
671 NumTextures = texture_count;
672 Num_tmaps = tmap_count;
674 Textures[NumTextures++].index = 0; //entry for bogus tmap
680 Assert(N_robot_types == Num_robot_ais); //should be one ai info per robot
683 init_endlevel(); //this is here so endlevel bitmaps go into pig
688 //check for refereced but unused clip count
689 for (i=0; i<MAX_EFFECTS; i++ )
691 (Effects[i].changing_wall_texture!=-1) ||
692 (Effects[i].changing_object_texture!=-1)
694 && (Effects[i].vc.num_frames==-1) )
695 Error("EClip %d referenced (by polygon object?), but not defined",i);
700 for (i=used=0; i<num_sounds; i++ )
701 if (Sounds[i] != 255)
703 mprintf((0,"Sound slots used: %d of %d, highest index %d\n",used,MAX_SOUNDS,num_sounds));
705 //make sure all alt sounds refer to valid main sounds
706 for (i=used=0; i<num_sounds; i++ ) {
707 int alt = AltSounds[i];
708 Assert(alt==0 || alt==-1 || Sounds[alt]!=255);
719 gr_use_palette_table(DEFAULT_PALETTE);
724 void verify_textures()
729 for (i=0; i<Num_tmaps; i++ ) {
730 bmp = &GameBitmaps[Textures[i].index];
731 if ( (bmp->bm_w!=64)||(bmp->bm_h!=64)||(bmp->bm_rowsize!=64) ) {
732 mprintf( (1, "ERROR: Texture '%s' isn't 64x64 !\n", TmapInfo[i].filename ));
737 Error("%d textures were not 64x64. See mono screen for list.",j);
739 for (i=0;i<Num_effects;i++)
740 if (Effects[i].changing_object_texture != -1)
741 if (GameBitmaps[ObjBitmaps[Effects[i].changing_object_texture].index].bm_w!=64 || GameBitmaps[ObjBitmaps[Effects[i].changing_object_texture].index].bm_h!=64)
742 Error("Effect %d is used on object, but is not 64x64",i);
750 Assert(Num_aliases < MAX_ALIASES);
752 t = strtok( NULL, space ); strncpy(alias_list[Num_aliases].alias_name,t,sizeof(alias_list[Num_aliases].alias_name));
753 t = strtok( NULL, space ); strncpy(alias_list[Num_aliases].file_name,t,sizeof(alias_list[Num_aliases].file_name));
758 //--unused-- void dump_all_transparent_textures()
760 //--unused-- FILE * fp;
761 //--unused-- int i,j,k;
762 //--unused-- ubyte * p;
763 //--unused-- fp = fopen( "XPARENT.LST", "wt" );
764 //--unused-- for (i=0; i<Num_tmaps; i++ ) {
766 //--unused-- p = Textures[i]->bm_data;
767 //--unused-- for (j=0; j<64*64; j++ )
768 //--unused-- if ( (*p++)==255 ) k++;
769 //--unused-- if ( k ) {
770 //--unused-- fprintf( fp, "'%s' has %d transparent pixels\n", TmapInfo[i].filename, k );
773 //--unused-- fclose(fp);
785 void set_lighting_flag(sbyte *bp)
788 *bp |= BM_FLAG_NO_LIGHTING;
790 *bp &= (0xff ^ BM_FLAG_NO_LIGHTING);
793 void set_texture_name(char *name)
795 strcpy ( TmapInfo[texture_count].filename, name );
796 REMOVE_DOTS(TmapInfo[texture_count].filename);
804 Assert(clip_num < MAX_EFFECTS);
806 if (clip_num+1 > Num_effects)
807 Num_effects = clip_num+1;
809 Effects[clip_num].flags = 0;
811 //load the dest bitmap first, so that after this routine, the last-loaded
812 //texture will be the monitor, so that lighting parameter will be applied
813 //to the correct texture
814 if (dest_bm) { //deal with bitmap for blown up clip
815 char short_name[FILENAME_LEN];
817 strcpy(short_name,dest_bm);
818 REMOVE_DOTS(short_name);
819 for (i=0;i<texture_count;i++)
820 if (!stricmp(TmapInfo[i].filename,short_name))
822 if (i==texture_count) {
823 Textures[texture_count] = bm_load_sub(dest_bm);
824 strcpy( TmapInfo[texture_count].filename, short_name);
826 Assert(texture_count < MAX_TEXTURES);
827 NumTextures = texture_count;
829 else if (Textures[i].index == 0) //was found, but registered out
830 Textures[i] = bm_load_sub(dest_bm);
835 bitmap = bm_load_sub(arg);
837 Effects[clip_num].vc.play_time = fl2f(time);
838 Effects[clip_num].vc.num_frames = frames;
839 Effects[clip_num].vc.frame_time = fl2f(time)/frames;
841 Assert(clip_count < frames);
842 Effects[clip_num].vc.frames[clip_count] = bitmap;
843 set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags);
845 Assert(!obj_eclip); //obj eclips for non-abm files not supported!
846 Assert(crit_flag==0);
848 if (clip_count == 0) {
849 Effects[clip_num].changing_wall_texture = texture_count;
850 Assert(tmap_count < MAX_TEXTURES);
851 TmapList[tmap_count++] = texture_count;
852 Textures[texture_count] = bitmap;
853 set_texture_name(arg);
854 Assert(texture_count < MAX_TEXTURES);
856 TmapInfo[texture_count].eclip_num = clip_num;
857 NumTextures = texture_count;
863 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
866 ab_load( arg, bm, &Effects[clip_num].vc.num_frames );
868 //printf("EC%d.", clip_num);
869 Effects[clip_num].vc.play_time = fl2f(time);
870 Effects[clip_num].vc.frame_time = Effects[clip_num].vc.play_time/Effects[clip_num].vc.num_frames;
873 set_lighting_flag( &GameBitmaps[bm[clip_count].index].bm_flags);
874 Effects[clip_num].vc.frames[clip_count] = bm[clip_count];
876 if (!obj_eclip && !crit_flag) {
877 Effects[clip_num].changing_wall_texture = texture_count;
878 Assert(tmap_count < MAX_TEXTURES);
879 TmapList[tmap_count++] = texture_count;
880 Textures[texture_count] = bm[clip_count];
881 set_texture_name( arg );
882 Assert(texture_count < MAX_TEXTURES);
883 TmapInfo[texture_count].eclip_num = clip_num;
885 NumTextures = texture_count;
890 if (Effects[clip_num].changing_object_texture == -1) { //first time referenced
891 Effects[clip_num].changing_object_texture = N_ObjBitmaps; // XChange ObjectBitmaps
895 ObjBitmaps[Effects[clip_num].changing_object_texture] = Effects[clip_num].vc.frames[0];
898 //if for an object, Effects_bm_ptrs set in object load
900 for(clip_count=1;clip_count < Effects[clip_num].vc.num_frames; clip_count++) {
901 set_lighting_flag( &GameBitmaps[bm[clip_count].index].bm_flags);
902 Effects[clip_num].vc.frames[clip_count] = bm[clip_count];
907 Effects[clip_num].crit_clip = crit_clip;
908 Effects[clip_num].sound_num = sound_num;
910 if (dest_bm) { //deal with bitmap for blown up clip
912 Effects[clip_num].dest_bm_num = dest_bm_num;
915 Error("Desctuction vclip missing on line %d",linenum);
917 Error("Desctuction vclip missing on line %d",linenum);
919 Effects[clip_num].dest_vclip = dest_vclip;
920 Effects[clip_num].dest_size = dest_size;
922 Effects[clip_num].dest_eclip = dest_eclip;
925 Effects[clip_num].dest_bm_num = -1;
926 Effects[clip_num].dest_eclip = -1;
930 Effects[clip_num].flags |= EF_CRITICAL;
934 void bm_read_gauges()
937 int i, num_abm_frames;
940 bitmap = bm_load_sub(arg);
941 Assert(clip_count < MAX_GAUGE_BMS);
942 Gauges[clip_count] = bitmap;
945 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
947 ab_load( arg, bm, &num_abm_frames );
948 for (i=clip_count; i<clip_count+num_abm_frames; i++) {
949 Assert(i < MAX_GAUGE_BMS);
950 Gauges[i] = bm[i-clip_count];
952 clip_count += num_abm_frames;
956 void bm_read_gauges_hires()
959 int i, num_abm_frames;
962 bitmap = bm_load_sub(arg);
963 Assert(clip_count < MAX_GAUGE_BMS);
964 Gauges_hires[clip_count] = bitmap;
967 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
969 ab_load( arg, bm, &num_abm_frames );
970 for (i=clip_count; i<clip_count+num_abm_frames; i++) {
971 Assert(i < MAX_GAUGE_BMS);
972 Gauges_hires[i] = bm[i-clip_count];
974 clip_count += num_abm_frames;
981 Assert(clip_num < MAX_WALL_ANIMS);
983 WallAnims[clip_num].flags = 0;
985 if (wall_explodes) WallAnims[clip_num].flags |= WCF_EXPLODES;
986 if (wall_blastable) WallAnims[clip_num].flags |= WCF_BLASTABLE;
987 if (wall_hidden) WallAnims[clip_num].flags |= WCF_HIDDEN;
988 if (tmap1_flag) WallAnims[clip_num].flags |= WCF_TMAP1;
991 bitmap = bm_load_sub(arg);
992 if ( (WallAnims[clip_num].num_frames>-1) && (clip_count==0) )
993 Error( "Wall Clip %d is already used!", clip_num );
994 WallAnims[clip_num].play_time = fl2f(time);
995 WallAnims[clip_num].num_frames = frames;
996 //WallAnims[clip_num].frame_time = fl2f(time)/frames;
997 Assert(clip_count < frames);
998 WallAnims[clip_num].frames[clip_count++] = texture_count;
999 WallAnims[clip_num].open_sound = wall_open_sound;
1000 WallAnims[clip_num].close_sound = wall_close_sound;
1001 Textures[texture_count] = bitmap;
1002 set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags);
1003 set_texture_name( arg );
1004 Assert(texture_count < MAX_TEXTURES);
1006 NumTextures = texture_count;
1007 if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1;
1009 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
1011 if ( (WallAnims[clip_num].num_frames>-1) )
1012 Error( "AB_Wall clip %d is already used!", clip_num );
1014 ab_load( arg, bm, &nframes );
1015 WallAnims[clip_num].num_frames = nframes;
1017 WallAnims[clip_num].play_time = fl2f(time);
1018 //WallAnims[clip_num].frame_time = fl2f(time)/nframes;
1019 WallAnims[clip_num].open_sound = wall_open_sound;
1020 WallAnims[clip_num].close_sound = wall_close_sound;
1022 WallAnims[clip_num].close_sound = wall_close_sound;
1023 strcpy(WallAnims[clip_num].filename, arg);
1024 REMOVE_DOTS(WallAnims[clip_num].filename);
1026 if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1;
1028 set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
1030 for (clip_count=0;clip_count < WallAnims[clip_num].num_frames; clip_count++) {
1031 //printf("%d", clip_count);
1032 Textures[texture_count] = bm[clip_count];
1033 set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
1034 WallAnims[clip_num].frames[clip_count] = texture_count;
1036 sprintf( TmapInfo[texture_count].filename, "%s#%d", arg, clip_count);
1037 Assert(texture_count < MAX_TEXTURES);
1039 NumTextures = texture_count;
1044 void bm_read_vclip()
1047 Assert(clip_num < VCLIP_MAXNUM);
1049 if (clip_num >= Num_vclips)
1050 Num_vclips = clip_num+1;
1053 if ( (Vclip[clip_num].num_frames>-1) && (clip_count==0) )
1054 Error( "Vclip %d is already used!", clip_num );
1055 bi = bm_load_sub(arg);
1056 Vclip[clip_num].play_time = fl2f(time);
1057 Vclip[clip_num].num_frames = frames;
1058 Vclip[clip_num].frame_time = fl2f(time)/frames;
1059 Vclip[clip_num].light_value = fl2f(vlighting);
1060 Vclip[clip_num].sound_num = sound_num;
1061 set_lighting_flag(&GameBitmaps[bi.index].bm_flags);
1062 Assert(clip_count < frames);
1063 Vclip[clip_num].frames[clip_count++] = bi;
1066 Vclip[clip_num].flags |= VF_ROD;
1070 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
1072 if ( (Vclip[clip_num].num_frames>-1) )
1073 Error( "AB_Vclip %d is already used!", clip_num );
1074 ab_load( arg, bm, &Vclip[clip_num].num_frames );
1079 Vclip[clip_num].flags |= VF_ROD;
1082 Vclip[clip_num].play_time = fl2f(time);
1083 Vclip[clip_num].frame_time = fl2f(time)/Vclip[clip_num].num_frames;
1084 Vclip[clip_num].light_value = fl2f(vlighting);
1085 Vclip[clip_num].sound_num = sound_num;
1086 set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
1088 for (clip_count=0;clip_count < Vclip[clip_num].num_frames; clip_count++) {
1089 //printf("%d", clip_count);
1090 set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
1091 Vclip[clip_num].frames[clip_count] = bm[clip_count];
1096 // ------------------------------------------------------------------------------
1097 void get4fix(fix *fixp)
1102 for (i=0; i<NDL; i++) {
1103 curtext = strtok(NULL, space);
1104 fixp[i] = fl2f(atof(curtext));
1108 // ------------------------------------------------------------------------------
1109 void get4byte(sbyte *bytep)
1114 for (i=0; i<NDL; i++) {
1115 curtext = strtok(NULL, space);
1116 bytep[i] = atoi(curtext);
1120 // ------------------------------------------------------------------------------
1121 // Convert field of view from an angle in 0..360 to cosine.
1122 void adjust_field_of_view(fix *fovp)
1129 for (i=0; i<NDL; i++) {
1130 ff = - f2fl(fovp[i]);
1132 mprintf((1, "Warning: Bogus field of view (%7.3f). Must be in 0..179.\n", ff));
1137 fix_sincos(tt, &temp, &fovp[i]);
1141 void clear_to_end_of_line(void)
1143 arg = strtok( NULL, space );
1145 arg = strtok( NULL, space );
1148 void bm_read_sound()
1153 sound_num = get_int();
1154 alt_sound_num = get_int();
1156 if ( sound_num>=MAX_SOUNDS )
1157 Error( "Too many sound files.\n" );
1159 if (sound_num >= num_sounds)
1160 num_sounds = sound_num+1;
1162 if (Sounds[sound_num] != 255)
1163 Error("Sound num %d already used, bitmaps.tbl, line %d\n",sound_num,linenum);
1165 arg = strtok(NULL, space);
1167 Sounds[sound_num] = ds_load(arg);
1169 if ( alt_sound_num == 0 )
1170 AltSounds[sound_num] = sound_num;
1171 else if (alt_sound_num < 0 )
1172 AltSounds[sound_num] = 255;
1174 AltSounds[sound_num] = alt_sound_num;
1176 if (Sounds[sound_num] == 255)
1177 Error("Can't load soundfile <%s>",arg);
1180 // ------------------------------------------------------------------------------
1181 void bm_read_robot_ai()
1183 char *robotnum_text;
1187 robotnum_text = strtok(NULL, space);
1188 robotnum = atoi(robotnum_text);
1189 Assert(robotnum < MAX_ROBOT_TYPES);
1190 robptr = &Robot_info[robotnum];
1192 Assert(robotnum == Num_robot_ais); //make sure valid number
1195 if (Registered_only) {
1197 clear_to_end_of_line();
1204 get4fix(robptr->field_of_view);
1205 get4fix(robptr->firing_wait);
1206 get4fix(robptr->firing_wait2);
1207 get4byte(robptr->rapidfire_count);
1208 get4fix(robptr->turn_time);
1209 // get4fix(robptr->fire_power);
1210 // get4fix(robptr->shield);
1211 get4fix(robptr->max_speed);
1212 get4fix(robptr->circle_distance);
1213 get4byte(robptr->evade_speed);
1215 robptr->always_0xabcd = 0xabcd;
1217 adjust_field_of_view(robptr->field_of_view);
1221 // ----------------------------------------------------------------------------------------------
1222 //this will load a bitmap for a polygon models. it puts the bitmap into
1223 //the array ObjBitmaps[], and also deals with animating bitmaps
1224 //returns a pointer to the bitmap
1225 grs_bitmap *load_polymodel_bitmap(char *name)
1227 Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
1229 // Assert( N_ObjBitmaps == N_ObjBitmapPtrs );
1231 if (name[0] == '%') { //an animating bitmap!
1234 eclip_num = atoi(name+1);
1236 if (Effects[eclip_num].changing_object_texture == -1) { //first time referenced
1237 Effects[eclip_num].changing_object_texture = N_ObjBitmaps;
1238 ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps;
1241 ObjBitmapPtrs[N_ObjBitmapPtrs++] = Effects[eclip_num].changing_object_texture;
1243 Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
1244 Assert(N_ObjBitmapPtrs < MAX_OBJ_BITMAPS);
1248 ObjBitmaps[N_ObjBitmaps] = bm_load_sub(name);
1249 if (GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_w!=64 || GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_h!=64)
1250 Error("Bitmap <%s> is not 64x64",name);
1251 ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps;
1253 Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
1254 Assert(N_ObjBitmapPtrs < MAX_OBJ_BITMAPS);
1255 return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index];
1259 #define MAX_MODEL_VARIANTS 4
1261 // ------------------------------------------------------------------------------
1262 void bm_read_robot()
1264 char *model_name[MAX_MODEL_VARIANTS];
1266 int first_bitmap_num[MAX_MODEL_VARIANTS];
1268 int exp1_vclip_num=-1;
1269 int exp1_sound_num=-1;
1270 int exp2_vclip_num=-1;
1271 int exp2_sound_num=-1;
1272 fix lighting = F1_0/2; // Default
1273 fix strength = F1_0*10; // Default strength
1276 short weapon_type = 0, weapon_type2 = -1;
1278 char name[ROBOT_NAME_LENGTH];
1279 int contains_count=0, contains_id=0, contains_prob=0, contains_type=0, behavior=AIB_NORMAL;
1280 int companion = 0, smart_blobs=0, energy_blobs=0, badass=0, energy_drain=0, kamikaze=0, thief=0, pursuit=0, lightcast=0, death_roll=0;
1281 fix glow=0, aim=F1_0;
1282 int deathroll_sound = SOUND_BOSS_SHARE_DIE; //default
1283 int score_value=1000;
1284 int cloak_type=0; // Default = this robot does not cloak
1285 int attack_type=0; // Default = this robot attacks by firing (1=lunge)
1286 int boss_flag=0; // Default = robot is not a boss.
1287 int see_sound = ROBOT_SEE_SOUND_DEFAULT;
1288 int attack_sound = ROBOT_ATTACK_SOUND_DEFAULT;
1289 int claw_sound = ROBOT_CLAW_SOUND_DEFAULT;
1290 int taunt_sound = ROBOT_SEE_SOUND_DEFAULT;
1293 Assert(N_robot_types < MAX_ROBOT_TYPES);
1296 if (Registered_only) {
1297 Robot_info[N_robot_types].model_num = -1;
1299 Assert(N_robot_types < MAX_ROBOT_TYPES);
1300 Num_total_object_types++;
1301 Assert(Num_total_object_types < MAX_OBJTYPE);
1302 clear_to_end_of_line();
1307 model_name[0] = strtok( NULL, space );
1308 first_bitmap_num[0] = N_ObjBitmapPtrs;
1313 arg = strtok( NULL, space );
1315 equal_ptr = strchr( arg, '=' );
1319 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1320 if (!stricmp( arg, "exp1_vclip" )) {
1321 exp1_vclip_num = atoi(equal_ptr);
1322 } else if (!stricmp( arg, "exp2_vclip" )) {
1323 exp2_vclip_num = atoi(equal_ptr);
1324 } else if (!stricmp( arg, "exp1_sound" )) {
1325 exp1_sound_num = atoi(equal_ptr);
1326 } else if (!stricmp( arg, "exp2_sound" )) {
1327 exp2_sound_num = atoi(equal_ptr);
1328 } else if (!stricmp( arg, "lighting" )) {
1329 lighting = fl2f(atof(equal_ptr));
1330 if ( (lighting < 0) || (lighting > F1_0 )) {
1331 mprintf( (1, "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)));
1332 Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting));
1334 } else if (!stricmp( arg, "weapon_type" )) {
1335 weapon_type = atoi(equal_ptr);
1336 } else if (!stricmp( arg, "weapon_type2" )) {
1337 weapon_type2 = atoi(equal_ptr);
1338 } else if (!stricmp( arg, "strength" )) {
1339 strength = i2f(atoi(equal_ptr));
1340 } else if (!stricmp( arg, "mass" )) {
1341 mass = fl2f(atof(equal_ptr));
1342 } else if (!stricmp( arg, "drag" )) {
1343 drag = fl2f(atof(equal_ptr));
1344 } else if (!stricmp( arg, "contains_id" )) {
1345 contains_id = atoi(equal_ptr);
1346 } else if (!stricmp( arg, "contains_type" )) {
1347 contains_type = atoi(equal_ptr);
1348 } else if (!stricmp( arg, "contains_count" )) {
1349 contains_count = atoi(equal_ptr);
1350 } else if (!stricmp( arg, "companion" )) {
1351 companion = atoi(equal_ptr);
1352 } else if (!stricmp( arg, "badass" )) {
1353 badass = atoi(equal_ptr);
1354 } else if (!stricmp( arg, "lightcast" )) {
1355 lightcast = atoi(equal_ptr);
1356 } else if (!stricmp( arg, "glow" )) {
1357 glow = fl2f(atof(equal_ptr));
1358 } else if (!stricmp( arg, "death_roll" )) {
1359 death_roll = atoi(equal_ptr);
1360 } else if (!stricmp( arg, "deathroll_sound" )) {
1361 deathroll_sound = atoi(equal_ptr);
1362 } else if (!stricmp( arg, "thief" )) {
1363 thief = atoi(equal_ptr);
1364 } else if (!stricmp( arg, "kamikaze" )) {
1365 kamikaze = atoi(equal_ptr);
1366 } else if (!stricmp( arg, "pursuit" )) {
1367 pursuit = atoi(equal_ptr);
1368 } else if (!stricmp( arg, "smart_blobs" )) {
1369 smart_blobs = atoi(equal_ptr);
1370 } else if (!stricmp( arg, "energy_blobs" )) {
1371 energy_blobs = atoi(equal_ptr);
1372 } else if (!stricmp( arg, "energy_drain" )) {
1373 energy_drain = atoi(equal_ptr);
1374 } else if (!stricmp( arg, "contains_prob" )) {
1375 contains_prob = atoi(equal_ptr);
1376 } else if (!stricmp( arg, "cloak_type" )) {
1377 cloak_type = atoi(equal_ptr);
1378 } else if (!stricmp( arg, "attack_type" )) {
1379 attack_type = atoi(equal_ptr);
1380 } else if (!stricmp( arg, "boss" )) {
1381 boss_flag = atoi(equal_ptr);
1382 } else if (!stricmp( arg, "score_value" )) {
1383 score_value = atoi(equal_ptr);
1384 } else if (!stricmp( arg, "see_sound" )) {
1385 see_sound = atoi(equal_ptr);
1386 } else if (!stricmp( arg, "attack_sound" )) {
1387 attack_sound = atoi(equal_ptr);
1388 } else if (!stricmp( arg, "claw_sound" )) {
1389 claw_sound = atoi(equal_ptr);
1390 } else if (!stricmp( arg, "taunt_sound" )) {
1391 taunt_sound = atoi(equal_ptr);
1392 } else if (!stricmp( arg, "aim" )) {
1393 aim = fl2f(atof(equal_ptr));
1394 } else if (!stricmp( arg, "big_radius" )) {
1395 if (atoi(equal_ptr))
1396 flags |= RIF_BIG_RADIUS;
1397 } else if (!stricmp( arg, "behavior" )) {
1398 if (!stricmp(equal_ptr, "STILL"))
1399 behavior = AIB_STILL;
1400 else if (!stricmp(equal_ptr, "NORMAL"))
1401 behavior = AIB_NORMAL;
1402 else if (!stricmp(equal_ptr, "BEHIND"))
1403 behavior = AIB_BEHIND;
1404 else if (!stricmp(equal_ptr, "RUN_FROM"))
1405 behavior = AIB_RUN_FROM;
1406 else if (!stricmp(equal_ptr, "SNIPE"))
1407 behavior = AIB_SNIPE;
1408 else if (!stricmp(equal_ptr, "STATION"))
1409 behavior = AIB_STATION;
1410 else if (!stricmp(equal_ptr, "FOLLOW"))
1411 behavior = AIB_FOLLOW;
1413 Int3(); // Error. Illegal behavior type for current robot.
1414 } else if (!stricmp( arg, "name" )) {
1415 Assert(strlen(equal_ptr) < ROBOT_NAME_LENGTH); // Oops, name too long.
1416 strcpy(name, &equal_ptr[1]);
1417 name[strlen(name)-1] = 0;
1418 } else if (!stricmp( arg, "simple_model" )) {
1419 model_name[n_models] = equal_ptr;
1420 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1422 Assert(n_models < MAX_MODEL_VARIANTS);
1425 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1427 } else { // Must be a texture specification...
1428 load_polymodel_bitmap(arg);
1430 arg = strtok( NULL, space );
1433 //clear out anim info
1434 for (g=0;g<MAX_GUNS+1;g++)
1435 for (s=0;s<N_ANIM_STATES;s++)
1436 Robot_info[N_robot_types].anim_states[g][s].n_joints = 0; //inialize to zero
1438 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1440 for (i=0;i<n_models;i++) {
1442 int model_num,last_model_num=0;
1444 n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
1446 model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],(i==0)?&Robot_info[N_robot_types]:NULL);
1449 Robot_info[N_robot_types].model_num = model_num;
1451 Polygon_models[last_model_num].simpler_model = model_num+1;
1453 last_model_num = model_num;
1456 if ((glow > i2f(15)) || (glow < 0) || (glow != 0 && glow < 0x1000)) {
1457 mprintf((0,"Invalid glow value %x for robot %d\n",glow,N_robot_types));
1461 ObjType[Num_total_object_types] = OL_ROBOT;
1462 ObjId[Num_total_object_types] = N_robot_types;
1464 Robot_info[N_robot_types].exp1_vclip_num = exp1_vclip_num;
1465 Robot_info[N_robot_types].exp2_vclip_num = exp2_vclip_num;
1466 Robot_info[N_robot_types].exp1_sound_num = exp1_sound_num;
1467 Robot_info[N_robot_types].exp2_sound_num = exp2_sound_num;
1468 Robot_info[N_robot_types].lighting = lighting;
1469 Robot_info[N_robot_types].weapon_type = weapon_type;
1470 Robot_info[N_robot_types].weapon_type2 = weapon_type2;
1471 Robot_info[N_robot_types].strength = strength;
1472 Robot_info[N_robot_types].mass = mass;
1473 Robot_info[N_robot_types].drag = drag;
1474 Robot_info[N_robot_types].cloak_type = cloak_type;
1475 Robot_info[N_robot_types].attack_type = attack_type;
1476 Robot_info[N_robot_types].boss_flag = boss_flag;
1478 Robot_info[N_robot_types].contains_id = contains_id;
1479 Robot_info[N_robot_types].contains_count = contains_count;
1480 Robot_info[N_robot_types].contains_prob = contains_prob;
1481 Robot_info[N_robot_types].companion = companion;
1482 Robot_info[N_robot_types].badass = badass;
1483 Robot_info[N_robot_types].lightcast = lightcast;
1484 Robot_info[N_robot_types].glow = (glow>>12); //convert to 4:4
1485 Robot_info[N_robot_types].death_roll = death_roll;
1486 Robot_info[N_robot_types].deathroll_sound = deathroll_sound;
1487 Robot_info[N_robot_types].thief = thief;
1488 Robot_info[N_robot_types].flags = flags;
1489 Robot_info[N_robot_types].kamikaze = kamikaze;
1490 Robot_info[N_robot_types].pursuit = pursuit;
1491 Robot_info[N_robot_types].smart_blobs = smart_blobs;
1492 Robot_info[N_robot_types].energy_blobs = energy_blobs;
1493 Robot_info[N_robot_types].energy_drain = energy_drain;
1494 Robot_info[N_robot_types].score_value = score_value;
1495 Robot_info[N_robot_types].see_sound = see_sound;
1496 Robot_info[N_robot_types].attack_sound = attack_sound;
1497 Robot_info[N_robot_types].claw_sound = claw_sound;
1498 Robot_info[N_robot_types].taunt_sound = taunt_sound;
1499 Robot_info[N_robot_types].behavior = behavior; // Default behavior for this robot, if coming out of matcen.
1500 Robot_info[N_robot_types].aim = min(f2i(aim*255), 255); // how well this robot type can aim. 255=perfect
1503 Robot_info[N_robot_types].contains_type = OBJ_ROBOT;
1505 Robot_info[N_robot_types].contains_type = OBJ_POWERUP;
1507 strcpy(Robot_names[N_robot_types], name);
1510 Num_total_object_types++;
1512 Assert(N_robot_types < MAX_ROBOT_TYPES);
1513 Assert(Num_total_object_types < MAX_OBJTYPE);
1518 //read a reactor model
1519 void bm_read_reactor()
1521 char *model_name, *model_name_dead=NULL;
1522 int first_bitmap_num, first_bitmap_num_dead=0, n_normal_bitmaps;
1525 short explosion_vclip_num = -1;
1526 short explosion_sound_num = SOUND_ROBOT_DESTROYED;
1527 fix lighting = F1_0/2; // Default
1531 Assert(Num_reactors < MAX_REACTORS);
1534 if (Registered_only) {
1536 clear_to_end_of_line();
1541 model_name = strtok( NULL, space );
1545 arg = strtok( NULL, space );
1546 first_bitmap_num = N_ObjBitmapPtrs;
1548 type = OL_CONTROL_CENTER;
1552 equal_ptr = strchr( arg, '=' );
1558 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1560 //@@if (!stricmp(arg,"type")) {
1561 //@@ if (!stricmp(equal_ptr,"controlcen"))
1562 //@@ type = OL_CONTROL_CENTER;
1563 //@@ else if (!stricmp(equal_ptr,"clutter"))
1564 //@@ type = OL_CLUTTER;
1567 if (!stricmp( arg, "exp_vclip" )) {
1568 explosion_vclip_num = atoi(equal_ptr);
1569 } else if (!stricmp( arg, "dead_pof" )) {
1570 model_name_dead = equal_ptr;
1571 first_bitmap_num_dead=N_ObjBitmapPtrs;
1572 } else if (!stricmp( arg, "exp_sound" )) {
1573 explosion_sound_num = atoi(equal_ptr);
1574 } else if (!stricmp( arg, "lighting" )) {
1575 lighting = fl2f(atof(equal_ptr));
1576 if ( (lighting < 0) || (lighting > F1_0 )) {
1577 mprintf( (1, "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)));
1578 Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting));
1580 } else if (!stricmp( arg, "strength" )) {
1581 strength = fl2f(atof(equal_ptr));
1584 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1586 } else { // Must be a texture specification...
1587 load_polymodel_bitmap(arg);
1589 arg = strtok( NULL, space );
1592 if ( model_name_dead )
1593 n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num;
1595 n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num;
1597 model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL);
1599 if ( model_name_dead )
1600 Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL);
1602 Dead_modelnums[model_num] = -1;
1605 Error("No object type specfied for object in BITMAPS.TBL on line %d\n",linenum);
1607 Reactors[Num_reactors].model_num = model_num;
1608 Reactors[Num_reactors].n_guns = read_model_guns(model_name,Reactors[Num_reactors].gun_points,Reactors[Num_reactors].gun_dirs,NULL);
1610 ObjType[Num_total_object_types] = type;
1611 ObjId[Num_total_object_types] = Num_reactors;
1612 ObjStrength[Num_total_object_types] = strength;
1614 //printf( "Object type %d is a control center\n", Num_total_object_types );
1615 Num_total_object_types++;
1616 Assert(Num_total_object_types < MAX_OBJTYPE);
1621 //read the marker object
1622 void bm_read_marker()
1625 int first_bitmap_num, n_normal_bitmaps;
1628 model_name = strtok( NULL, space );
1632 arg = strtok( NULL, space );
1633 first_bitmap_num = N_ObjBitmapPtrs;
1637 equal_ptr = strchr( arg, '=' );
1643 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1644 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1647 } else { // Must be a texture specification...
1648 load_polymodel_bitmap(arg);
1650 arg = strtok( NULL, space );
1653 n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num;
1655 Marker_model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL);
1659 //read the exit model
1660 void bm_read_exitmodel()
1662 char *model_name, *model_name_dead=NULL;
1663 int first_bitmap_num, first_bitmap_num_dead, n_normal_bitmaps;
1667 model_name = strtok( NULL, space );
1671 arg = strtok( NULL, space );
1672 first_bitmap_num = N_ObjBitmapPtrs;
1676 equal_ptr = strchr( arg, '=' );
1682 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1684 if (!stricmp( arg, "dead_pof" )) {
1685 model_name_dead = equal_ptr;
1686 first_bitmap_num_dead=N_ObjBitmapPtrs;
1689 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1691 } else { // Must be a texture specification...
1692 load_polymodel_bitmap(arg);
1694 arg = strtok( NULL, space );
1697 if ( model_name_dead )
1698 n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num;
1700 n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num;
1702 model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL);
1704 if ( model_name_dead )
1705 Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL);
1707 Dead_modelnums[model_num] = -1;
1709 //@@ ObjType[Num_total_object_types] = type;
1710 //@@ ObjId[Num_total_object_types] = model_num;
1711 //@@ ObjStrength[Num_total_object_types] = strength;
1713 //@@ //printf( "Object type %d is a control center\n", Num_total_object_types );
1714 //@@ Num_total_object_types++;
1715 //@@ Assert(Num_total_object_types < MAX_OBJTYPE);
1717 exit_modelnum = model_num;
1718 destroyed_exit_modelnum = Dead_modelnums[model_num];
1723 void bm_read_player_ship()
1725 char *model_name_dying=NULL;
1726 char *model_name[MAX_MODEL_VARIANTS];
1728 int first_bitmap_num[MAX_MODEL_VARIANTS];
1731 int last_multi_bitmap_num=-1;
1736 arg = strtok( NULL, space );
1738 Player_ship->mass = Player_ship->drag = 0; //stupid defaults
1739 Player_ship->expl_vclip_num = -1;
1743 equal_ptr = strchr( arg, '=' );
1750 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1752 if (!stricmp( arg, "model" )) {
1753 Assert(n_models==0);
1754 model_name[0] = equal_ptr;
1755 first_bitmap_num[0] = N_ObjBitmapPtrs;
1757 } else if (!stricmp( arg, "simple_model" )) {
1758 model_name[n_models] = equal_ptr;
1759 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1761 Assert(n_models < MAX_MODEL_VARIANTS);
1763 if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1)
1764 last_multi_bitmap_num=N_ObjBitmapPtrs;
1766 else if (!stricmp( arg, "mass" ))
1767 Player_ship->mass = fl2f(atof(equal_ptr));
1768 else if (!stricmp( arg, "drag" ))
1769 Player_ship->drag = fl2f(atof(equal_ptr));
1770 // else if (!stricmp( arg, "low_thrust" ))
1771 // Player_ship->low_thrust = fl2f(atof(equal_ptr));
1772 else if (!stricmp( arg, "max_thrust" ))
1773 Player_ship->max_thrust = fl2f(atof(equal_ptr));
1774 else if (!stricmp( arg, "reverse_thrust" ))
1775 Player_ship->reverse_thrust = fl2f(atof(equal_ptr));
1776 else if (!stricmp( arg, "brakes" ))
1777 Player_ship->brakes = fl2f(atof(equal_ptr));
1778 else if (!stricmp( arg, "wiggle" ))
1779 Player_ship->wiggle = fl2f(atof(equal_ptr));
1780 else if (!stricmp( arg, "max_rotthrust" ))
1781 Player_ship->max_rotthrust = fl2f(atof(equal_ptr));
1782 else if (!stricmp( arg, "dying_pof" ))
1783 model_name_dying = equal_ptr;
1784 else if (!stricmp( arg, "expl_vclip_num" ))
1785 Player_ship->expl_vclip_num=atoi(equal_ptr);
1788 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1791 else if (!stricmp( arg, "multi_textures" )) {
1793 First_multi_bitmap_num = N_ObjBitmapPtrs;
1794 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1797 else // Must be a texture specification...
1799 load_polymodel_bitmap(arg);
1801 arg = strtok( NULL, space );
1804 Assert(model_name != NULL);
1806 if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1)
1807 last_multi_bitmap_num=N_ObjBitmapPtrs;
1809 if (First_multi_bitmap_num==-1)
1810 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1813 Assert(last_multi_bitmap_num-First_multi_bitmap_num == (MAX_NUM_NET_PLAYERS-1)*2);
1816 for (i=0;i<n_models;i++) {
1818 int model_num,last_model_num=0;
1820 n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
1822 model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],(i==0)?&ri:NULL);
1825 Player_ship->model_num = model_num;
1827 Polygon_models[last_model_num].simpler_model = model_num+1;
1829 last_model_num = model_num;
1832 if ( model_name_dying ) {
1834 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);
1837 Assert(ri.n_guns == N_PLAYER_GUNS);
1839 //calc player gun positions
1845 int mn; //submodel number
1849 pm = &Polygon_models[Player_ship->model_num];
1851 for (gun_num=0;gun_num<r->n_guns;gun_num++) {
1853 pnt = r->gun_points[gun_num];
1854 mn = r->gun_submodels[gun_num];
1856 //instance up the tree for this gun
1858 vm_vec_add2(&pnt,&pm->submodel_offsets[mn]);
1859 mn = pm->submodel_parents[mn];
1862 Player_ship->gun_points[gun_num] = pnt;
1870 void bm_read_some_file()
1875 Error("Trying to read bitmap <%s> with bm_flag==BM_NONE on line %d of BITMAPS.TBL",arg,linenum);
1878 bitmap_index bitmap;
1879 bitmap = bm_load_sub(arg);
1880 Assert( Num_cockpits < N_COCKPIT_BITMAPS );
1881 cockpit_bitmap[Num_cockpits++] = bitmap;
1882 //bm_flag = BM_NONE;
1890 case BM_GAUGES_HIRES:
1891 bm_read_gauges_hires();
1907 bitmap_index bitmap;
1908 bitmap = bm_load_sub(arg);
1909 Assert(tmap_count < MAX_TEXTURES);
1910 TmapList[tmap_count++] = texture_count;
1911 Textures[texture_count] = bitmap;
1912 set_texture_name( arg );
1913 Assert(texture_count < MAX_TEXTURES);
1915 NumTextures = texture_count;
1925 Error("Trying to read bitmap <%s> with unknown bm_flag <%x> on line %d of BITMAPS.TBL",arg,bm_flag,linenum);
1928 // ------------------------------------------------------------------------------
1929 // If unused_flag is set, then this is just a placeholder. Don't actually reference vclips or load bbms.
1930 void bm_read_weapon(int unused_flag)
1935 char *pof_file_inner=NULL;
1936 char *model_name[MAX_MODEL_VARIANTS];
1937 int first_bitmap_num[MAX_MODEL_VARIANTS];
1938 int lighted; //flag for whether is a texture is lighted
1940 Assert(N_weapon_types < MAX_WEAPON_TYPES);
1944 Assert(N_weapon_types <= MAX_WEAPON_TYPES);
1947 clear_to_end_of_line();
1952 if (Registered_only) {
1953 clear_to_end_of_line();
1958 // Initialize weapon array
1959 Weapon_info[n].render_type = WEAPON_RENDER_NONE; // 0=laser, 1=blob, 2=object
1960 Weapon_info[n].bitmap.index = 0;
1961 Weapon_info[n].model_num = -1;
1962 Weapon_info[n].model_num_inner = -1;
1963 Weapon_info[n].blob_size = 0x1000; // size of blob
1964 Weapon_info[n].flash_vclip = -1;
1965 Weapon_info[n].flash_sound = SOUND_LASER_FIRED;
1966 Weapon_info[n].flash_size = 0;
1967 Weapon_info[n].robot_hit_vclip = -1;
1968 Weapon_info[n].robot_hit_sound = -1;
1969 Weapon_info[n].wall_hit_vclip = -1;
1970 Weapon_info[n].wall_hit_sound = -1;
1971 Weapon_info[n].impact_size = 0;
1972 for (i=0; i<NDL; i++) {
1973 Weapon_info[n].strength[i] = F1_0;
1974 Weapon_info[n].speed[i] = F1_0*10;
1976 Weapon_info[n].mass = F1_0;
1977 Weapon_info[n].thrust = 0;
1978 Weapon_info[n].drag = 0;
1979 Weapon_info[n].persistent = 0;
1981 Weapon_info[n].energy_usage = 0; // How much fuel is consumed to fire this weapon.
1982 Weapon_info[n].ammo_usage = 0; // How many units of ammunition it uses.
1983 Weapon_info[n].fire_wait = F1_0/4; // Time until this weapon can be fired again.
1984 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.
1985 Weapon_info[n].damage_radius = 0; // Radius of damage for missiles, not lasers. Does damage to objects within this radius of hit point.
1986 //--01/19/95, mk-- Weapon_info[n].damage_force = 0; // Force (movement) due to explosion
1987 Weapon_info[n].destroyable = 1; // Weapons default to destroyable
1988 Weapon_info[n].matter = 0; // Weapons default to not being constructed of matter (they are energy!)
1989 Weapon_info[n].bounce = 0; // Weapons default to not bouncing off walls
1991 Weapon_info[n].flags = 0;
1993 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.
1995 Weapon_info[n].po_len_to_width_ratio = F1_0*10;
1997 Weapon_info[n].picture.index = 0;
1998 Weapon_info[n].hires_picture.index = 0;
1999 Weapon_info[n].homing_flag = 0;
2001 Weapon_info[n].flash = 0;
2002 Weapon_info[n].multi_damage_scale = F1_0;
2003 Weapon_info[n].afterburner_size = 0;
2004 Weapon_info[n].children = -1;
2006 // Process arguments
2007 arg = strtok( NULL, space );
2009 lighted = 1; //assume first texture is lighted
2011 Weapon_info[n].speedvar = 128;
2014 equal_ptr = strchr( arg, '=' );
2018 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
2019 if (!stricmp( arg, "laser_bmp" )) {
2020 // Load bitmap with name equal_ptr
2022 Weapon_info[n].bitmap = bm_load_sub(equal_ptr); //load_polymodel_bitmap(equal_ptr);
2023 Weapon_info[n].render_type = WEAPON_RENDER_LASER;
2025 } else if (!stricmp( arg, "blob_bmp" )) {
2026 // Load bitmap with name equal_ptr
2028 Weapon_info[n].bitmap = bm_load_sub(equal_ptr); //load_polymodel_bitmap(equal_ptr);
2029 Weapon_info[n].render_type = WEAPON_RENDER_BLOB;
2031 } else if (!stricmp( arg, "weapon_vclip" )) {
2032 // Set vclip to play for this weapon.
2033 Weapon_info[n].bitmap.index = 0;
2034 Weapon_info[n].render_type = WEAPON_RENDER_VCLIP;
2035 Weapon_info[n].weapon_vclip = atoi(equal_ptr);
2037 } else if (!stricmp( arg, "none_bmp" )) {
2038 Weapon_info[n].bitmap = bm_load_sub(equal_ptr);
2039 Weapon_info[n].render_type = WEAPON_RENDER_NONE;
2041 } else if (!stricmp( arg, "weapon_pof" )) {
2043 Assert(n_models==0);
2044 model_name[0] = equal_ptr;
2045 first_bitmap_num[0] = N_ObjBitmapPtrs;
2047 } else if (!stricmp( arg, "simple_model" )) {
2048 model_name[n_models] = equal_ptr;
2049 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
2051 Assert(n_models < MAX_MODEL_VARIANTS);
2052 } else if (!stricmp( arg, "weapon_pof_inner" )) {
2054 pof_file_inner = equal_ptr;
2055 } else if (!stricmp( arg, "strength" )) {
2056 for (i=0; i<NDL-1; i++) {
2057 Weapon_info[n].strength[i] = fl2f(atof(equal_ptr));
2058 equal_ptr = strtok(NULL, space);
2060 Weapon_info[n].strength[i] = i2f(atoi(equal_ptr));
2061 } else if (!stricmp( arg, "mass" )) {
2062 Weapon_info[n].mass = fl2f(atof(equal_ptr));
2063 } else if (!stricmp( arg, "drag" )) {
2064 Weapon_info[n].drag = fl2f(atof(equal_ptr));
2065 } else if (!stricmp( arg, "thrust" )) {
2066 Weapon_info[n].thrust = fl2f(atof(equal_ptr));
2067 } else if (!stricmp( arg, "matter" )) {
2068 Weapon_info[n].matter = atoi(equal_ptr);
2069 } else if (!stricmp( arg, "bounce" )) {
2070 Weapon_info[n].bounce = atoi(equal_ptr);
2071 } else if (!stricmp( arg, "speed" )) {
2072 for (i=0; i<NDL-1; i++) {
2073 Weapon_info[n].speed[i] = i2f(atoi(equal_ptr));
2074 equal_ptr = strtok(NULL, space);
2076 Weapon_info[n].speed[i] = i2f(atoi(equal_ptr));
2077 } else if (!stricmp( arg, "speedvar" )) {
2078 Weapon_info[n].speedvar = (atoi(equal_ptr) * 128) / 100;
2079 } else if (!stricmp( arg, "flash_vclip" )) {
2080 Weapon_info[n].flash_vclip = atoi(equal_ptr);
2081 } else if (!stricmp( arg, "flash_sound" )) {
2082 Weapon_info[n].flash_sound = atoi(equal_ptr);
2083 } else if (!stricmp( arg, "flash_size" )) {
2084 Weapon_info[n].flash_size = fl2f(atof(equal_ptr));
2085 } else if (!stricmp( arg, "blob_size" )) {
2086 Weapon_info[n].blob_size = fl2f(atof(equal_ptr));
2087 } else if (!stricmp( arg, "robot_hit_vclip" )) {
2088 Weapon_info[n].robot_hit_vclip = atoi(equal_ptr);
2089 } else if (!stricmp( arg, "robot_hit_sound" )) {
2090 Weapon_info[n].robot_hit_sound = atoi(equal_ptr);
2091 } else if (!stricmp( arg, "wall_hit_vclip" )) {
2092 Weapon_info[n].wall_hit_vclip = atoi(equal_ptr);
2093 } else if (!stricmp( arg, "wall_hit_sound" )) {
2094 Weapon_info[n].wall_hit_sound = atoi(equal_ptr);
2095 } else if (!stricmp( arg, "impact_size" )) {
2096 Weapon_info[n].impact_size = fl2f(atof(equal_ptr));
2097 } else if (!stricmp( arg, "lighted" )) {
2098 lighted = atoi(equal_ptr);
2099 } else if (!stricmp( arg, "lw_ratio" )) {
2100 Weapon_info[n].po_len_to_width_ratio = fl2f(atof(equal_ptr));
2101 } else if (!stricmp( arg, "lightcast" )) {
2102 Weapon_info[n].light = fl2f(atof(equal_ptr));
2103 } else if (!stricmp( arg, "persistent" )) {
2104 Weapon_info[n].persistent = atoi(equal_ptr);
2105 } else if (!stricmp(arg, "energy_usage" )) {
2106 Weapon_info[n].energy_usage = fl2f(atof(equal_ptr));
2107 } else if (!stricmp(arg, "ammo_usage" )) {
2108 Weapon_info[n].ammo_usage = atoi(equal_ptr);
2109 } else if (!stricmp(arg, "fire_wait" )) {
2110 Weapon_info[n].fire_wait = fl2f(atof(equal_ptr));
2111 } else if (!stricmp(arg, "fire_count" )) {
2112 Weapon_info[n].fire_count = atoi(equal_ptr);
2113 } else if (!stricmp(arg, "damage_radius" )) {
2114 Weapon_info[n].damage_radius = fl2f(atof(equal_ptr));
2115 //--01/19/95, mk-- } else if (!stricmp(arg, "damage_force" )) {
2116 //--01/19/95, mk-- Weapon_info[n].damage_force = fl2f(atof(equal_ptr));
2117 } else if (!stricmp(arg, "lifetime" )) {
2118 Weapon_info[n].lifetime = fl2f(atof(equal_ptr));
2119 } else if (!stricmp(arg, "destroyable" )) {
2120 Weapon_info[n].destroyable = atoi(equal_ptr);
2121 } else if (!stricmp(arg, "picture" )) {
2122 Weapon_info[n].picture = bm_load_sub(equal_ptr);
2123 } else if (!stricmp(arg, "hires_picture" )) {
2124 Weapon_info[n].hires_picture = bm_load_sub(equal_ptr);
2125 } else if (!stricmp(arg, "homing" )) {
2126 Weapon_info[n].homing_flag = !!atoi(equal_ptr);
2127 } else if (!stricmp(arg, "flash" )) {
2128 Weapon_info[n].flash = atoi(equal_ptr);
2129 } else if (!stricmp(arg, "multi_damage_scale" )) {
2130 Weapon_info[n].multi_damage_scale = fl2f(atof(equal_ptr));
2131 } else if (!stricmp(arg, "afterburner_size" )) {
2132 Weapon_info[n].afterburner_size = f2i(16*fl2f(atof(equal_ptr)));
2133 } else if (!stricmp(arg, "children" )) {
2134 Weapon_info[n].children = atoi(equal_ptr);
2135 } else if (!stricmp(arg, "placable" )) {
2136 if (atoi(equal_ptr)) {
2137 Weapon_info[n].flags |= WIF_PLACABLE;
2139 Assert(Num_total_object_types < MAX_OBJTYPE);
2140 ObjType[Num_total_object_types] = OL_WEAPON;
2141 ObjId[Num_total_object_types] = n;
2142 Num_total_object_types++;
2146 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
2148 } else { // Must be a texture specification...
2151 bm = load_polymodel_bitmap(arg);
2153 bm->bm_flags |= BM_FLAG_NO_LIGHTING;
2155 lighted = 1; //default for next bitmap is lighted
2157 arg = strtok( NULL, space );
2160 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
2162 for (i=0;i<n_models;i++) {
2164 int model_num,last_model_num=0;
2166 n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
2168 model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],NULL);
2171 Weapon_info[n].render_type = WEAPON_RENDER_POLYMODEL;
2172 Weapon_info[n].model_num = model_num;
2175 Polygon_models[last_model_num].simpler_model = model_num+1;
2177 last_model_num = model_num;
2180 if ( pof_file_inner ) {
2182 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);
2185 if ((Weapon_info[n].ammo_usage == 0) && (Weapon_info[n].energy_usage == 0))
2186 mprintf((1, "Warning: Weapon %i has ammo and energy usage of 0.\n", n));
2188 // -- render type of none is now legal -- Assert( Weapon_info[n].render_type != WEAPON_RENDER_NONE );
2195 // ------------------------------------------------------------------------------
2196 #define DEFAULT_POWERUP_SIZE i2f(3)
2198 void bm_read_powerup(int unused_flag)
2203 Assert(N_powerup_types < MAX_POWERUP_TYPES);
2205 n = N_powerup_types;
2209 clear_to_end_of_line();
2213 // Initialize powerup array
2214 Powerup_info[n].light = F1_0/3; // Default lighting value.
2215 Powerup_info[n].vclip_num = -1;
2216 Powerup_info[n].hit_sound = -1;
2217 Powerup_info[n].size = DEFAULT_POWERUP_SIZE;
2218 Powerup_names[n][0] = 0;
2220 // Process arguments
2221 arg = strtok( NULL, space );
2224 equal_ptr = strchr( arg, '=' );
2228 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
2229 if (!stricmp( arg, "vclip_num" )) {
2230 Powerup_info[n].vclip_num = atoi(equal_ptr);
2231 } else if (!stricmp( arg, "light" )) {
2232 Powerup_info[n].light = fl2f(atof(equal_ptr));
2233 } else if (!stricmp( arg, "hit_sound" )) {
2234 Powerup_info[n].hit_sound = atoi(equal_ptr);
2235 } else if (!stricmp( arg, "name" )) {
2236 Assert(strlen(equal_ptr) < POWERUP_NAME_LENGTH); // Oops, name too long.
2237 strcpy(Powerup_names[n], &equal_ptr[1]);
2238 Powerup_names[n][strlen(Powerup_names[n])-1] = 0;
2239 } else if (!stricmp( arg, "size" )) {
2240 Powerup_info[n].size = fl2f(atof(equal_ptr));
2243 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
2245 } else { // Must be a texture specification...
2247 mprintf( (1, "Invalid argument, %s in bitmaps.tbl\n", arg ));
2249 arg = strtok( NULL, space );
2252 ObjType[Num_total_object_types] = OL_POWERUP;
2253 ObjId[Num_total_object_types] = n;
2254 //printf( "Object type %d is a powerup\n", Num_total_object_types );
2255 Num_total_object_types++;
2256 Assert(Num_total_object_types < MAX_OBJTYPE);
2260 void bm_read_hostage()
2265 Assert(N_hostage_types < MAX_HOSTAGE_TYPES);
2267 n = N_hostage_types;
2270 // Process arguments
2271 arg = strtok( NULL, space );
2274 equal_ptr = strchr( arg, '=' );
2279 if (!stricmp( arg, "vclip_num" ))
2281 Hostage_vclip_num[n] = atoi(equal_ptr);
2285 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
2290 mprintf( (1, "Invalid argument, %s in bitmaps.tbl at line %d\n", arg, linenum ));
2292 arg = strtok( NULL, space );
2295 ObjType[Num_total_object_types] = OL_HOSTAGE;
2296 ObjId[Num_total_object_types] = n;
2297 //printf( "Object type %d is a hostage\n", Num_total_object_types );
2298 Num_total_object_types++;
2299 Assert(Num_total_object_types < MAX_OBJTYPE);
2303 //these values are the number of each item in the release of d2
2304 //extra items added after the release get written in an additional hamfile
2305 #define N_D2_ROBOT_TYPES 66
2306 #define N_D2_ROBOT_JOINTS 1145
2307 #define N_D2_POLYGON_MODELS 166
2308 #define N_D2_OBJBITMAPS 422
2309 #define N_D2_OBJBITMAPPTRS 502
2310 #define N_D2_WEAPON_TYPES 62
2312 void bm_write_all(FILE *fp)
2318 tfile = fopen("hamfile.lst","wt");
2320 t = NumTextures-1; //don't save bogus texture
2321 fwrite( &t, sizeof(int), 1, fp );
2322 fwrite( Textures, sizeof(bitmap_index), t, fp );
2324 fwrite( &TmapInfo[i], sizeof(*TmapInfo)-sizeof(TmapInfo->filename)-sizeof(TmapInfo->pad2), 1, fp );
2326 fprintf(tfile,"NumTextures = %d, Textures array = %d, TmapInfo array = %d\n",NumTextures,sizeof(bitmap_index)*NumTextures,sizeof(tmap_info)*NumTextures);
2329 fwrite( &t, sizeof(int), 1, fp );
2330 fwrite( Sounds, sizeof(ubyte), t, fp );
2331 fwrite( AltSounds, sizeof(ubyte), t, fp );
2333 fprintf(tfile,"Num Sounds = %d, Sounds array = %d, AltSounds array = %d\n",t,t,t);
2335 fwrite( &Num_vclips, sizeof(int), 1, fp );
2336 fwrite( Vclip, sizeof(vclip), Num_vclips, fp );
2338 fprintf(tfile,"Num_vclips = %d, Vclip array = %d\n",Num_vclips,sizeof(vclip)*Num_vclips);
2340 fwrite( &Num_effects, sizeof(int), 1, fp );
2341 fwrite( Effects, sizeof(eclip), Num_effects, fp );
2343 fprintf(tfile,"Num_effects = %d, Effects array = %d\n",Num_effects,sizeof(eclip)*Num_effects);
2345 fwrite( &Num_wall_anims, sizeof(int), 1, fp );
2346 fwrite( WallAnims, sizeof(wclip), Num_wall_anims, fp );
2348 fprintf(tfile,"Num_wall_anims = %d, WallAnims array = %d\n",Num_wall_anims,sizeof(wclip)*Num_wall_anims);
2350 t = N_D2_ROBOT_TYPES;
2351 fwrite( &t, sizeof(int), 1, fp );
2352 fwrite( Robot_info, sizeof(robot_info), t, fp );
2354 fprintf(tfile,"N_robot_types = %d, Robot_info array = %d\n",t,sizeof(robot_info)*N_robot_types);
2356 t = N_D2_ROBOT_JOINTS;
2357 fwrite( &t, sizeof(int), 1, fp );
2358 fwrite( Robot_joints, sizeof(jointpos), t, fp );
2360 fprintf(tfile,"N_robot_joints = %d, Robot_joints array = %d\n",t,sizeof(jointpos)*N_robot_joints);
2362 t = N_D2_WEAPON_TYPES;
2363 fwrite( &t, sizeof(int), 1, fp );
2364 fwrite( Weapon_info, sizeof(weapon_info), t, fp );
2366 fprintf(tfile,"N_weapon_types = %d, Weapon_info array = %d\n",N_weapon_types,sizeof(weapon_info)*N_weapon_types);
2368 fwrite( &N_powerup_types, sizeof(int), 1, fp );
2369 fwrite( Powerup_info, sizeof(powerup_type_info), N_powerup_types, fp );
2371 fprintf(tfile,"N_powerup_types = %d, Powerup_info array = %d\n",N_powerup_types,sizeof(powerup_info)*N_powerup_types);
2373 t = N_D2_POLYGON_MODELS;
2374 fwrite( &t, sizeof(int), 1, fp );
2375 fwrite( Polygon_models, sizeof(polymodel), t, fp );
2377 fprintf(tfile,"N_polygon_models = %d, Polygon_models array = %d\n",t,sizeof(polymodel)*t);
2379 for (i=0; i<t; i++ ) {
2380 g3_uninit_polygon_model(Polygon_models[i].model_data); //get RGB colors
2381 fwrite( Polygon_models[i].model_data, sizeof(ubyte), Polygon_models[i].model_data_size, fp );
2382 fprintf(tfile," Model %d, data size = %d\n",i,Polygon_models[i].model_data_size); s+=Polygon_models[i].model_data_size;
2383 g3_init_polygon_model(Polygon_models[i].model_data); //map colors again
2385 fprintf(tfile,"Total model size = %d\n",s);
2387 fwrite( Dying_modelnums, sizeof(int), t, fp );
2388 fwrite( Dead_modelnums, sizeof(int), t, fp );
2390 fprintf(tfile,"Dying_modelnums array = %d, Dead_modelnums array = %d\n",sizeof(int)*t,sizeof(int)*t);
2393 fwrite( &t, sizeof(int), 1, fp );
2394 fwrite( Gauges, sizeof(bitmap_index), t, fp );
2395 fwrite( Gauges_hires, sizeof(bitmap_index), t, fp );
2397 fprintf(tfile,"Num gauge bitmaps = %d, Gauges array = %d, Gauges_hires array = %d\n",t,sizeof(bitmap_index)*t,sizeof(bitmap_index)*t);
2399 t = MAX_OBJ_BITMAPS;
2400 fwrite( &t, sizeof(int), 1, fp );
2401 fwrite( ObjBitmaps, sizeof(bitmap_index), t, fp );
2402 fwrite( ObjBitmapPtrs, sizeof(ushort), t, fp );
2404 fprintf(tfile,"Num obj bitmaps = %d, ObjBitmaps array = %d, ObjBitmapPtrs array = %d\n",t,sizeof(bitmap_index)*t,sizeof(ushort)*t);
2406 fwrite( &only_player_ship, sizeof(player_ship), 1, fp );
2408 fprintf(tfile,"player_ship size = %d\n",sizeof(player_ship));
2410 fwrite( &Num_cockpits, sizeof(int), 1, fp );
2411 fwrite( cockpit_bitmap, sizeof(bitmap_index), Num_cockpits, fp );
2413 fprintf(tfile,"Num_cockpits = %d, cockpit_bitmaps array = %d\n",Num_cockpits,sizeof(bitmap_index)*Num_cockpits);
2415 //@@ fwrite( &Num_total_object_types, sizeof(int), 1, fp );
2416 //@@ fwrite( ObjType, sizeof(sbyte), Num_total_object_types, fp );
2417 //@@ fwrite( ObjId, sizeof(sbyte), Num_total_object_types, fp );
2418 //@@ fwrite( ObjStrength, sizeof(fix), Num_total_object_types, fp );
2420 fprintf(tfile,"Num_total_object_types = %d, ObjType array = %d, ObjId array = %d, ObjStrength array = %d\n",Num_total_object_types,Num_total_object_types,Num_total_object_types,sizeof(fix)*Num_total_object_types);
2422 fwrite( &First_multi_bitmap_num, sizeof(int), 1, fp );
2424 fwrite( &Num_reactors, sizeof(Num_reactors), 1, fp );
2425 fwrite( Reactors, sizeof(*Reactors), Num_reactors, fp);
2427 fprintf(tfile,"Num_reactors = %d, Reactors array = %d\n",Num_reactors,sizeof(*Reactors)*Num_reactors);
2429 fwrite( &Marker_model_num, sizeof(Marker_model_num), 1, fp);
2431 //@@fwrite( &N_controlcen_guns, sizeof(int), 1, fp );
2432 //@@fwrite( controlcen_gun_points, sizeof(vms_vector), N_controlcen_guns, fp );
2433 //@@fwrite( controlcen_gun_dirs, sizeof(vms_vector), N_controlcen_guns, fp );
2436 fwrite( &exit_modelnum, sizeof(int), 1, fp );
2437 fwrite( &destroyed_exit_modelnum, sizeof(int), 1, fp );
2442 bm_write_extra_robots();
2445 void bm_write_extra_robots()
2451 fp = fopen("robots.ham","wb");
2453 t = 0x5848414d; /* 'XHAM' */
2454 fwrite( &t, sizeof(int), 1, fp );
2456 fwrite( &t, sizeof(int), 1, fp );
2459 t = N_weapon_types - N_D2_WEAPON_TYPES;
2460 fwrite( &t, sizeof(int), 1, fp );
2461 fwrite( &Weapon_info[N_D2_WEAPON_TYPES], sizeof(weapon_info), t, fp );
2463 //now write robot info
2465 t = N_robot_types - N_D2_ROBOT_TYPES;
2466 fwrite( &t, sizeof(int), 1, fp );
2467 fwrite( &Robot_info[N_D2_ROBOT_TYPES], sizeof(robot_info), t, fp );
2469 t = N_robot_joints - N_D2_ROBOT_JOINTS;
2470 fwrite( &t, sizeof(int), 1, fp );
2471 fwrite( &Robot_joints[N_D2_ROBOT_JOINTS], sizeof(jointpos), t, fp );
2473 t = N_polygon_models - N_D2_POLYGON_MODELS;
2474 fwrite( &t, sizeof(int), 1, fp );
2475 fwrite( &Polygon_models[N_D2_POLYGON_MODELS], sizeof(polymodel), t, fp );
2477 for (i=N_D2_POLYGON_MODELS; i<N_polygon_models; i++ ) {
2478 g3_uninit_polygon_model(Polygon_models[i].model_data); //get RGB colors
2479 fwrite( Polygon_models[i].model_data, sizeof(ubyte), Polygon_models[i].model_data_size, fp );
2480 g3_init_polygon_model(Polygon_models[i].model_data); //map colors again
2483 fwrite( &Dying_modelnums[N_D2_POLYGON_MODELS], sizeof(int), t, fp );
2484 fwrite( &Dead_modelnums[N_D2_POLYGON_MODELS], sizeof(int), t, fp );
2486 t = N_ObjBitmaps - N_D2_OBJBITMAPS;
2487 fwrite( &t, sizeof(int), 1, fp );
2488 fwrite( &ObjBitmaps[N_D2_OBJBITMAPS], sizeof(bitmap_index), t, fp );
2490 t = N_ObjBitmapPtrs - N_D2_OBJBITMAPPTRS;
2491 fwrite( &t, sizeof(int), 1, fp );
2492 fwrite( &ObjBitmapPtrs[N_D2_OBJBITMAPPTRS], sizeof(ushort), t, fp );
2494 fwrite( ObjBitmapPtrs, sizeof(ushort), t, fp );