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-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
16 * Routines to parse bitmaps.tbl
17 * Only used for editor, since the registered version of descent 1.
42 #include "editor/texpage.h"
55 #define BM_WALL_ANIMS 12
59 #define BM_GAUGES_HIRES 21
61 #define MAX_BITMAPS_PER_BRUSH 30
63 extern player_ship only_player_ship; // In bm.c
65 extern short N_ObjBitmaps; // in bm.c
66 short N_ObjBitmapPtrs=0;
67 static int Num_robot_ais = 0;
68 int TmapList[MAX_TEXTURES];
69 char Powerup_names[MAX_POWERUP_TYPES][POWERUP_NAME_LENGTH];
70 char Robot_names[MAX_ROBOT_TYPES][ROBOT_NAME_LENGTH];
72 //---------------- Internal variables ---------------------------
73 static int Registered_only = 0; // Gets set by ! in column 1.
74 static int SuperX = -1;
75 static int Installed=0;
77 static short tmap_count = 0;
78 static short texture_count = 0;
79 static short clip_count = 0;
80 static short clip_num;
81 static short sound_num;
83 static float play_time;
84 static int hit_sound = -1;
85 static sbyte bm_flag = BM_NONE;
86 static int abm_flag = 0;
87 static int rod_flag = 0;
88 static short wall_open_sound, wall_close_sound,wall_explodes,wall_blastable, wall_hidden;
91 static char *dest_bm; //clip number to play when destroyed
92 static int dest_vclip; //what vclip to play when exploding
93 static int dest_eclip; //what eclip to play when exploding
94 static fix dest_size; //3d size of explosion
95 static int crit_clip; //clip number to play when destroyed
96 static int crit_flag; //flag if this is a destroyed eclip
97 static int tmap1_flag; //flag if this is used as tmap_num (not tmap_num2)
98 static int num_sounds=0;
100 int linenum; //line int table currently being parsed
102 //------------------- Useful macros and variables ---------------
103 extern void remove_char( char * s, char c ); // in piggy.c
104 #define REMOVE_EOL(s) remove_char((s),'\n')
105 #define REMOVE_COMMENTS(s) remove_char((s),';')
106 #define REMOVE_DOTS(s) remove_char((s),'.')
108 #define IFTOK(str) if (!strcmp(arg, str))
109 extern char *space; // in piggy.c
110 //--unused-- char *equal = { "=" };
111 extern char *equal_space; // in piggy.c
114 // For the sake of LINT, defining prototypes to module's functions
115 void bm_read_alias(void);
116 void bm_read_marker(void);
117 void bm_read_robot_ai(void);
118 void bm_read_powerup(int unused_flag);
119 void bm_read_hostage(void);
120 void bm_read_robot(void);
121 void bm_read_weapon(int unused_flag);
122 void bm_read_reactor(void);
123 void bm_read_exitmodel(void);
124 void bm_read_player_ship(void);
125 void bm_read_some_file(void);
126 void bm_read_sound(void);
127 void bm_write_extra_robots(void);
128 void clear_to_end_of_line(void);
129 void verify_textures(void);
132 //---------------------------------------------------------------
133 int compute_average_pixel(grs_bitmap *new)
135 int row, column, color;
137 int total_red, total_green, total_blue;
139 pptr = (char *)new->bm_data;
145 for (row=0; row<new->bm_h; row++)
146 for (column=0; column<new->bm_w; column++) {
148 total_red += gr_palette[color*3];
149 total_green += gr_palette[color*3+1];
150 total_blue += gr_palette[color*3+2];
153 total_red /= (new->bm_h * new->bm_w);
154 total_green /= (new->bm_h * new->bm_w);
155 total_blue /= (new->bm_h * new->bm_w);
157 return BM_XRGB(total_red/2, total_green/2, total_blue/2);
160 //---------------------------------------------------------------
161 // Loads a bitmap from either the piggy file, a r64 file, or a
162 // whatever extension is passed.
164 bitmap_index bm_load_sub( char * filename )
166 bitmap_index bitmap_num;
169 int iff_error; //reference parm to avoid warning message
172 bitmap_num.index = 0;
175 if (Registered_only) {
176 //mprintf( 0, "Skipping registered-only bitmap '%s'\n", filename );
181 _splitpath( filename, NULL, NULL, fname, NULL );
183 bitmap_num=piggy_find_bitmap( fname );
184 if (bitmap_num.index) {
185 //mprintf(( 0, "Found bitmap '%s' in pig!\n", fname ));
189 MALLOC( new, grs_bitmap, 1 );
190 iff_error = iff_read_bitmap(filename,new,BM_LINEAR,newpal);
192 if (iff_error != IFF_NO_ERROR) {
193 mprintf((1, "File %s - IFF error: %s",filename,iff_errormsg(iff_error)));
194 Error("File <%s> - IFF error: %s, line %d",filename,iff_errormsg(iff_error),linenum);
197 if ( iff_has_transparency )
198 gr_remap_bitmap_good( new, newpal, iff_transparent_color, SuperX );
200 gr_remap_bitmap_good( new, newpal, -1, SuperX );
202 new->avg_color = compute_average_pixel(new);
204 // -- mprintf((0, "N" ));
205 bitmap_num = piggy_register_bitmap( new, fname, 0 );
210 extern ubyte bogus_bitmap_initialized;
211 extern digi_sound bogus_sound;
213 void ab_load( char * filename, bitmap_index bmp[], int *nframes )
215 grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH];
218 int iff_error; //reference parm to avoid warning message
224 if (Registered_only) {
225 Assert( bogus_bitmap_initialized != 0 );
226 mprintf(( 0, "Skipping registered-only animation '%s'\n", filename ));
227 bmp[0].index = 0; //index of bogus bitmap==0 (I think) //&bogus_bitmap;
234 _splitpath( filename, NULL, NULL, fname, NULL );
236 for (i=0; i<MAX_BITMAPS_PER_BRUSH; i++ ) {
237 sprintf( tempname, "%.8s#%d", fname, i );
238 bi = piggy_find_bitmap( tempname );
242 //mprintf(( 0, "Found animation frame %d, %s, in piggy file\n", i, tempname ));
250 // Note that last argument passes an address to the array newpal (which is a pointer).
251 // type mismatch found using lint, will substitute this line with an adjusted
252 // one. If fatal error, then it can be easily changed.
253 // iff_error = iff_read_animbrush(filename,bm,MAX_BITMAPS_PER_BRUSH,nframes,&newpal);
254 iff_error = iff_read_animbrush(filename,bm,MAX_BITMAPS_PER_BRUSH,nframes,newpal);
255 if (iff_error != IFF_NO_ERROR) {
256 mprintf((1,"File %s - IFF error: %s",filename,iff_errormsg(iff_error)));
257 Error("File <%s> - IFF error: %s, line %d",filename,iff_errormsg(iff_error),linenum);
260 for (i=0;i< *nframes; i++) {
261 bitmap_index new_bmp;
262 sprintf( tempname, "%.8s#%d", fname, i );
263 if ( iff_has_transparency )
264 gr_remap_bitmap_good( bm[i], newpal, iff_transparent_color, SuperX );
266 gr_remap_bitmap_good( bm[i], newpal, -1, SuperX );
268 bm[i]->avg_color = compute_average_pixel(bm[i]);
270 new_bmp = piggy_register_bitmap( bm[i], tempname, 0 );
274 mprintf((0, "Registering %s in piggy file.", tempname ));
281 int ds_load( char * filename ) {
289 if (Registered_only) {
290 //mprintf( 0, "Skipping registered-only sound '%s'\n", filename );
291 return 0; //don't know what I should return here //&bogus_sound;
295 removeext(filename, fname);
296 sprintf(rawname, "%s.%s", fname, (digi_sample_rate==SAMPLE_RATE_22K) ? "r22" : "raw");
298 i=piggy_find_sound( fname );
303 cfp = cfopen( rawname, "rb" );
306 new.length = cfilelength( cfp );
307 MALLOC( new.data, ubyte, new.length );
308 cfread( new.data, 1, new.length, cfp );
310 // -- mprintf( (0, "S" ));
311 // -- mprintf( (0, "<%s>", rawname ));
313 mprintf( (1, "Warning: Couldn't find '%s'\n", filename ));
316 i = piggy_register_sound( &new, fname, 0 );
325 xarg = strtok( NULL, space );
334 xarg = strtok( NULL, space );
338 // rotates a byte left one bit, preserving the bit falling off the right
340 //rotate_left(char *c)
352 //loads a texture and returns the texture num
353 int get_texture(char *name)
355 char short_name[FILENAME_LEN];
358 strcpy(short_name,name);
359 REMOVE_DOTS(short_name);
360 for (i=0;i<texture_count;i++)
361 if (!stricmp(TmapInfo[i].filename,short_name))
363 if (i==texture_count) {
364 Textures[texture_count] = bm_load_sub(name);
365 strcpy( TmapInfo[texture_count].filename, short_name);
367 Assert(texture_count < MAX_TEXTURES);
368 NumTextures = texture_count;
374 #define LINEBUF_SIZE 600
376 #define DEFAULT_PIG_PALETTE "groupa.256"
378 //-----------------------------------------------------------------
379 // Initializes all bitmaps from BITMAPS.TBL file.
380 // This is called when the editor is IN.
381 // If no editor, bm_init() is called.
382 int bm_init_use_tbl()
385 char inputline[LINEBUF_SIZE];
388 // Open BITMAPS.TBL for reading.
390 InfoFile = cfopen( "BITMAPS.TBL", "rb" );
391 if (InfoFile == NULL) {
392 InfoFile = cfopen("BITMAPS.BIN", "rb");
393 if (InfoFile == NULL)
394 return 0; //missing BITMAPS.TBL and BITMAPS.BIN file
398 gr_use_palette_table(DEFAULT_PIG_PALETTE);
400 load_palette(DEFAULT_PIG_PALETTE,-2,0); //special: tell palette code which pig is loaded
402 init_polygon_models();
404 for (i=0; i<MAX_SOUNDS; i++ ) {
409 for (i=0; i<MAX_TEXTURES; i++ ) {
410 TmapInfo[i].eclip_num = -1;
411 TmapInfo[i].flags = 0;
412 TmapInfo[i].slide_u = TmapInfo[i].slide_v = 0;
413 TmapInfo[i].destroyed = -1;
416 for (i=0;i<MAX_REACTORS;i++)
417 Reactors[i].model_num = -1;
420 for (i=0; i<MAX_EFFECTS; i++ ) {
421 //Effects[i].bm_ptr = (grs_bitmap **) -1;
422 Effects[i].changing_wall_texture = -1;
423 Effects[i].changing_object_texture = -1;
424 Effects[i].segnum = -1;
425 Effects[i].vc.num_frames = -1; //another mark of being unused
428 for (i=0;i<MAX_POLYGON_MODELS;i++)
429 Dying_modelnums[i] = Dead_modelnums[i] = -1;
432 for (i=0; i<VCLIP_MAXNUM; i++ ) {
433 Vclip[i].num_frames = -1;
437 for (i=0; i<MAX_WALL_ANIMS; i++ )
438 WallAnims[i].num_frames = -1;
441 setbuf(stdout, NULL); // unbuffered output via printf
448 piggy_init(); //don't care about error, since no pig is ok for editor
450 // if ( FindArg( "-nobm" ) ) {
451 // piggy_read_sounds();
456 cfseek( InfoFile, 0L, SEEK_SET);
458 while (cfgets(inputline, LINEBUF_SIZE, InfoFile)) {
464 if (inputline[0]==' ' || inputline[0]=='\t') {
466 for (t=inputline;*t && *t!='\n';t++)
467 if (! (*t==' ' || *t=='\t')) {
468 mprintf((1,"Suspicious: line %d of BITMAPS.TBL starts with whitespace\n",linenum));
473 if (have_bin_tbl) { // is this a binary tbl file
474 decode_text_line (inputline);
476 while (inputline[(l = (int)strlen(inputline)) - 2] == '\\') {
477 if (!isspace(inputline[l-3])) { //if not space before backslash...
478 inputline[l-2] = ' '; //add one
481 cfgets(inputline+l-2,LINEBUF_SIZE-(l-2), InfoFile);
486 REMOVE_EOL(inputline);
487 if (strchr(inputline, ';')!=NULL) REMOVE_COMMENTS(inputline);
489 if (strlen(inputline) == LINEBUF_SIZE-1)
490 Error("Possible line truncation in BITMAPS.TBL on line %d\n",linenum);
494 if ( (temp_ptr=strstr( inputline, "superx=" )) ) {
495 SuperX = atoi( &temp_ptr[7] );
496 Assert(SuperX == 254);
497 //the superx color isn't kept around, so the new piggy regeneration
498 //code doesn't know what it is, so it assumes that it's 254, so
499 //this code requires that it be 254
503 arg = strtok( inputline, space );
512 // Check all possible flags and defines.
513 if (*arg == '$') bm_flag = BM_NONE; // reset to no flags as default.
515 IFTOK("$COCKPIT") bm_flag = BM_COCKPIT;
516 else IFTOK("$GAUGES") {bm_flag = BM_GAUGES; clip_count = 0;}
517 else IFTOK("$GAUGES_HIRES"){bm_flag = BM_GAUGES_HIRES; clip_count = 0;}
518 else IFTOK("$SOUND") bm_read_sound();
519 else IFTOK("$DOOR_ANIMS") bm_flag = BM_WALL_ANIMS;
520 else IFTOK("$WALL_ANIMS") bm_flag = BM_WALL_ANIMS;
521 else IFTOK("$TEXTURES") bm_flag = BM_TEXTURES;
522 else IFTOK("$VCLIP") {bm_flag = BM_VCLIP; vlighting = 0; clip_count = 0;}
523 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;}
524 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;}
526 else IFTOK("$EFFECTS") {bm_flag = BM_EFFECTS; clip_num = 0;}
527 else IFTOK("$ALIAS") bm_read_alias();
530 else IFTOK("!METALS_FLAG") TextureMetals = texture_count;
531 else IFTOK("!LIGHTS_FLAG") TextureLights = texture_count;
532 else IFTOK("!EFFECTS_FLAG") TextureEffects = texture_count;
535 else IFTOK("lighting") TmapInfo[texture_count-1].lighting = fl2f(get_float());
536 else IFTOK("damage") TmapInfo[texture_count-1].damage = fl2f(get_float());
537 else IFTOK("volatile") TmapInfo[texture_count-1].flags |= TMI_VOLATILE;
538 else IFTOK("goal_blue") TmapInfo[texture_count-1].flags |= TMI_GOAL_BLUE;
539 else IFTOK("goal_red") TmapInfo[texture_count-1].flags |= TMI_GOAL_RED;
540 else IFTOK("water") TmapInfo[texture_count-1].flags |= TMI_WATER;
541 else IFTOK("force_field") TmapInfo[texture_count-1].flags |= TMI_FORCE_FIELD;
542 else IFTOK("slide") {TmapInfo[texture_count-1].slide_u = fl2f(get_float())>>8; TmapInfo[texture_count-1].slide_v = fl2f(get_float())>>8;}
543 else IFTOK("destroyed") {int t=texture_count-1; TmapInfo[t].destroyed = get_texture(strtok( NULL, space ));}
544 //else IFTOK("Num_effects") Num_effects = get_int();
545 else IFTOK("Num_wall_anims") Num_wall_anims = get_int();
546 else IFTOK("clip_num") clip_num = get_int();
547 else IFTOK("dest_bm") dest_bm = strtok( NULL, space );
548 else IFTOK("dest_vclip") dest_vclip = get_int();
549 else IFTOK("dest_eclip") dest_eclip = get_int();
550 else IFTOK("dest_size") dest_size = fl2f(get_float());
551 else IFTOK("crit_clip") crit_clip = get_int();
552 else IFTOK("crit_flag") crit_flag = get_int();
553 else IFTOK("sound_num") sound_num = get_int();
554 else IFTOK("frames") frames = get_int();
555 else IFTOK("time") play_time = get_float();
556 else IFTOK("obj_eclip") obj_eclip = get_int();
557 else IFTOK("hit_sound") hit_sound = get_int();
558 else IFTOK("abm_flag") abm_flag = get_int();
559 else IFTOK("tmap1_flag") tmap1_flag = get_int();
560 else IFTOK("vlighting") vlighting = get_float();
561 else IFTOK("rod_flag") rod_flag = get_int();
562 else IFTOK("superx") get_int();
563 else IFTOK("open_sound") wall_open_sound = get_int();
564 else IFTOK("close_sound") wall_close_sound = get_int();
565 else IFTOK("explodes") wall_explodes = get_int();
566 else IFTOK("blastable") wall_blastable = get_int();
567 else IFTOK("hidden") wall_hidden = get_int();
568 else IFTOK("$ROBOT_AI") bm_read_robot_ai();
570 else IFTOK("$POWERUP") {bm_read_powerup(0); continue;}
571 else IFTOK("$POWERUP_UNUSED") {bm_read_powerup(1); continue;}
572 else IFTOK("$HOSTAGE") {bm_read_hostage(); continue;}
573 else IFTOK("$ROBOT") {bm_read_robot(); continue;}
574 else IFTOK("$WEAPON") {bm_read_weapon(0); continue;}
575 else IFTOK("$WEAPON_UNUSED") {bm_read_weapon(1); continue;}
576 else IFTOK("$REACTOR") {bm_read_reactor(); continue;}
577 else IFTOK("$MARKER") {bm_read_marker(); continue;}
578 else IFTOK("$PLAYER_SHIP") {bm_read_player_ship(); continue;}
579 else IFTOK("$EXIT") {
583 clear_to_end_of_line();
587 else { //not a special token, must be a bitmap!
589 // Remove any illegal/unwanted spaces and tabs at this point.
590 while ((*arg=='\t') || (*arg==' ')) arg++;
591 if (*arg == '\0') { break; }
593 //check for '=' in token, indicating error
595 Error("Unknown token <'%s'> on line %d of BITMAPS.TBL",arg,linenum);
597 // Otherwise, 'arg' is apparently a bitmap filename.
598 // Load bitmap and process it below:
603 arg = strtok( NULL, equal_space );
608 NumTextures = texture_count;
609 Num_tmaps = tmap_count;
611 Textures[NumTextures++].index = 0; //entry for bogus tmap
617 Assert(N_robot_types == Num_robot_ais); //should be one ai info per robot
620 init_endlevel(); //this is here so endlevel bitmaps go into pig
625 //check for refereced but unused clip count
626 for (i=0; i<MAX_EFFECTS; i++ )
628 (Effects[i].changing_wall_texture!=-1) ||
629 (Effects[i].changing_object_texture!=-1)
631 && (Effects[i].vc.num_frames==-1) )
632 Error("EClip %d referenced (by polygon object?), but not defined",i);
637 for (i=used=0; i<num_sounds; i++ )
638 if (Sounds[i] != 255)
640 mprintf((0,"Sound slots used: %d of %d, highest index %d\n",used,MAX_SOUNDS,num_sounds));
642 //make sure all alt sounds refer to valid main sounds
643 for (i=used=0; i<num_sounds; i++ ) {
644 int alt = AltSounds[i];
645 Assert(alt==0 || alt==-1 || Sounds[alt]!=255);
656 gr_use_palette_table(D2_DEFAULT_PALETTE);
661 void verify_textures()
666 for (i=0; i<Num_tmaps; i++ ) {
667 bmp = &GameBitmaps[Textures[i].index];
668 if ( (bmp->bm_w!=64)||(bmp->bm_h!=64)||(bmp->bm_rowsize!=64) ) {
669 mprintf( (1, "ERROR: Texture '%s' isn't 64x64 !\n", TmapInfo[i].filename ));
674 Error("%d textures were not 64x64. See mono screen for list.",j);
676 for (i=0;i<Num_effects;i++)
677 if (Effects[i].changing_object_texture != -1)
678 if (GameBitmaps[ObjBitmaps[Effects[i].changing_object_texture].index].bm_w!=64 || GameBitmaps[ObjBitmaps[Effects[i].changing_object_texture].index].bm_h!=64)
679 Error("Effect %d is used on object, but is not 64x64",i);
687 Assert(Num_aliases < MAX_ALIASES);
689 t = strtok( NULL, space ); strncpy(alias_list[Num_aliases].alias_name,t,sizeof(alias_list[Num_aliases].alias_name));
690 t = strtok( NULL, space ); strncpy(alias_list[Num_aliases].file_name,t,sizeof(alias_list[Num_aliases].file_name));
695 //--unused-- void dump_all_transparent_textures()
697 //--unused-- FILE * fp;
698 //--unused-- int i,j,k;
699 //--unused-- ubyte * p;
700 //--unused-- fp = fopen( "XPARENT.LST", "wt" );
701 //--unused-- for (i=0; i<Num_tmaps; i++ ) {
703 //--unused-- p = Textures[i]->bm_data;
704 //--unused-- for (j=0; j<64*64; j++ )
705 //--unused-- if ( (*p++)==255 ) k++;
706 //--unused-- if ( k ) {
707 //--unused-- fprintf( fp, "'%s' has %d transparent pixels\n", TmapInfo[i].filename, k );
710 //--unused-- fclose(fp);
722 void set_lighting_flag(sbyte *bp)
725 *bp |= BM_FLAG_NO_LIGHTING;
727 *bp &= (0xff ^ BM_FLAG_NO_LIGHTING);
730 void set_texture_name(char *name)
732 strcpy ( TmapInfo[texture_count].filename, name );
733 REMOVE_DOTS(TmapInfo[texture_count].filename);
741 Assert(clip_num < MAX_EFFECTS);
743 if (clip_num+1 > Num_effects)
744 Num_effects = clip_num+1;
746 Effects[clip_num].flags = 0;
748 //load the dest bitmap first, so that after this routine, the last-loaded
749 //texture will be the monitor, so that lighting parameter will be applied
750 //to the correct texture
751 if (dest_bm) { //deal with bitmap for blown up clip
752 char short_name[FILENAME_LEN];
754 strcpy(short_name,dest_bm);
755 REMOVE_DOTS(short_name);
756 for (i=0;i<texture_count;i++)
757 if (!stricmp(TmapInfo[i].filename,short_name))
759 if (i==texture_count) {
760 Textures[texture_count] = bm_load_sub(dest_bm);
761 strcpy( TmapInfo[texture_count].filename, short_name);
763 Assert(texture_count < MAX_TEXTURES);
764 NumTextures = texture_count;
766 else if (Textures[i].index == 0) //was found, but registered out
767 Textures[i] = bm_load_sub(dest_bm);
772 bitmap = bm_load_sub(arg);
774 Effects[clip_num].vc.play_time = fl2f(play_time);
775 Effects[clip_num].vc.num_frames = frames;
776 Effects[clip_num].vc.frame_time = fl2f(play_time)/frames;
778 Assert(clip_count < frames);
779 Effects[clip_num].vc.frames[clip_count] = bitmap;
780 set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags);
782 Assert(!obj_eclip); //obj eclips for non-abm files not supported!
783 Assert(crit_flag==0);
785 if (clip_count == 0) {
786 Effects[clip_num].changing_wall_texture = texture_count;
787 Assert(tmap_count < MAX_TEXTURES);
788 TmapList[tmap_count++] = texture_count;
789 Textures[texture_count] = bitmap;
790 set_texture_name(arg);
791 Assert(texture_count < MAX_TEXTURES);
793 TmapInfo[texture_count].eclip_num = clip_num;
794 NumTextures = texture_count;
800 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
803 ab_load( arg, bm, &Effects[clip_num].vc.num_frames );
805 //printf("EC%d.", clip_num);
806 Effects[clip_num].vc.play_time = fl2f(play_time);
807 Effects[clip_num].vc.frame_time = Effects[clip_num].vc.play_time/Effects[clip_num].vc.num_frames;
810 set_lighting_flag( &GameBitmaps[bm[clip_count].index].bm_flags);
811 Effects[clip_num].vc.frames[clip_count] = bm[clip_count];
813 if (!obj_eclip && !crit_flag) {
814 Effects[clip_num].changing_wall_texture = texture_count;
815 Assert(tmap_count < MAX_TEXTURES);
816 TmapList[tmap_count++] = texture_count;
817 Textures[texture_count] = bm[clip_count];
818 set_texture_name( arg );
819 Assert(texture_count < MAX_TEXTURES);
820 TmapInfo[texture_count].eclip_num = clip_num;
822 NumTextures = texture_count;
827 if (Effects[clip_num].changing_object_texture == -1) { //first time referenced
828 Effects[clip_num].changing_object_texture = N_ObjBitmaps; // XChange ObjectBitmaps
832 ObjBitmaps[Effects[clip_num].changing_object_texture] = Effects[clip_num].vc.frames[0];
835 //if for an object, Effects_bm_ptrs set in object load
837 for(clip_count=1;clip_count < Effects[clip_num].vc.num_frames; clip_count++) {
838 set_lighting_flag( &GameBitmaps[bm[clip_count].index].bm_flags);
839 Effects[clip_num].vc.frames[clip_count] = bm[clip_count];
844 Effects[clip_num].crit_clip = crit_clip;
845 Effects[clip_num].sound_num = sound_num;
847 if (dest_bm) { //deal with bitmap for blown up clip
849 Effects[clip_num].dest_bm_num = dest_bm_num;
852 Error("Desctuction vclip missing on line %d",linenum);
854 Error("Desctuction vclip missing on line %d",linenum);
856 Effects[clip_num].dest_vclip = dest_vclip;
857 Effects[clip_num].dest_size = dest_size;
859 Effects[clip_num].dest_eclip = dest_eclip;
862 Effects[clip_num].dest_bm_num = -1;
863 Effects[clip_num].dest_eclip = -1;
867 Effects[clip_num].flags |= EF_CRITICAL;
871 void bm_read_gauges()
874 int i, num_abm_frames;
877 bitmap = bm_load_sub(arg);
878 Assert(clip_count < MAX_GAUGE_BMS);
879 Gauges[clip_count] = bitmap;
882 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
884 ab_load( arg, bm, &num_abm_frames );
885 for (i=clip_count; i<clip_count+num_abm_frames; i++) {
886 Assert(i < MAX_GAUGE_BMS);
887 Gauges[i] = bm[i-clip_count];
889 clip_count += num_abm_frames;
893 void bm_read_gauges_hires()
896 int i, num_abm_frames;
899 bitmap = bm_load_sub(arg);
900 Assert(clip_count < MAX_GAUGE_BMS);
901 Gauges_hires[clip_count] = bitmap;
904 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
906 ab_load( arg, bm, &num_abm_frames );
907 for (i=clip_count; i<clip_count+num_abm_frames; i++) {
908 Assert(i < MAX_GAUGE_BMS);
909 Gauges_hires[i] = bm[i-clip_count];
911 clip_count += num_abm_frames;
918 Assert(clip_num < MAX_WALL_ANIMS);
920 WallAnims[clip_num].flags = 0;
922 if (wall_explodes) WallAnims[clip_num].flags |= WCF_EXPLODES;
923 if (wall_blastable) WallAnims[clip_num].flags |= WCF_BLASTABLE;
924 if (wall_hidden) WallAnims[clip_num].flags |= WCF_HIDDEN;
925 if (tmap1_flag) WallAnims[clip_num].flags |= WCF_TMAP1;
928 bitmap = bm_load_sub(arg);
929 if ( (WallAnims[clip_num].num_frames>-1) && (clip_count==0) )
930 Error( "Wall Clip %d is already used!", clip_num );
931 WallAnims[clip_num].play_time = fl2f(play_time);
932 WallAnims[clip_num].num_frames = frames;
933 //WallAnims[clip_num].frame_time = fl2f(play_time)/frames;
934 Assert(clip_count < frames);
935 WallAnims[clip_num].frames[clip_count++] = texture_count;
936 WallAnims[clip_num].open_sound = wall_open_sound;
937 WallAnims[clip_num].close_sound = wall_close_sound;
938 Textures[texture_count] = bitmap;
939 set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags);
940 set_texture_name( arg );
941 Assert(texture_count < MAX_TEXTURES);
943 NumTextures = texture_count;
944 if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1;
946 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
948 if ( (WallAnims[clip_num].num_frames>-1) )
949 Error( "AB_Wall clip %d is already used!", clip_num );
951 ab_load( arg, bm, &nframes );
952 WallAnims[clip_num].num_frames = nframes;
954 WallAnims[clip_num].play_time = fl2f(play_time);
955 //WallAnims[clip_num].frame_time = fl2f(play_time)/nframes;
956 WallAnims[clip_num].open_sound = wall_open_sound;
957 WallAnims[clip_num].close_sound = wall_close_sound;
959 WallAnims[clip_num].close_sound = wall_close_sound;
960 strcpy(WallAnims[clip_num].filename, arg);
961 REMOVE_DOTS(WallAnims[clip_num].filename);
963 if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1;
965 set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
967 for (clip_count=0;clip_count < WallAnims[clip_num].num_frames; clip_count++) {
968 //printf("%d", clip_count);
969 Textures[texture_count] = bm[clip_count];
970 set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
971 WallAnims[clip_num].frames[clip_count] = texture_count;
973 sprintf( TmapInfo[texture_count].filename, "%s#%d", arg, clip_count);
974 Assert(texture_count < MAX_TEXTURES);
976 NumTextures = texture_count;
984 Assert(clip_num < VCLIP_MAXNUM);
986 if (clip_num >= Num_vclips)
987 Num_vclips = clip_num+1;
990 if ( (Vclip[clip_num].num_frames>-1) && (clip_count==0) )
991 Error( "Vclip %d is already used!", clip_num );
992 bi = bm_load_sub(arg);
993 Vclip[clip_num].play_time = fl2f(play_time);
994 Vclip[clip_num].num_frames = frames;
995 Vclip[clip_num].frame_time = fl2f(play_time)/frames;
996 Vclip[clip_num].light_value = fl2f(vlighting);
997 Vclip[clip_num].sound_num = sound_num;
998 set_lighting_flag(&GameBitmaps[bi.index].bm_flags);
999 Assert(clip_count < frames);
1000 Vclip[clip_num].frames[clip_count++] = bi;
1003 Vclip[clip_num].flags |= VF_ROD;
1007 bitmap_index bm[MAX_BITMAPS_PER_BRUSH];
1009 if ( (Vclip[clip_num].num_frames>-1) )
1010 Error( "AB_Vclip %d is already used!", clip_num );
1011 ab_load( arg, bm, &Vclip[clip_num].num_frames );
1016 Vclip[clip_num].flags |= VF_ROD;
1019 Vclip[clip_num].play_time = fl2f(play_time);
1020 Vclip[clip_num].frame_time = fl2f(play_time)/Vclip[clip_num].num_frames;
1021 Vclip[clip_num].light_value = fl2f(vlighting);
1022 Vclip[clip_num].sound_num = sound_num;
1023 set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
1025 for (clip_count=0;clip_count < Vclip[clip_num].num_frames; clip_count++) {
1026 //printf("%d", clip_count);
1027 set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags);
1028 Vclip[clip_num].frames[clip_count] = bm[clip_count];
1033 // ------------------------------------------------------------------------------
1034 void get4fix(fix *fixp)
1039 for (i=0; i<NDL; i++) {
1040 curtext = strtok(NULL, space);
1041 fixp[i] = fl2f(atof(curtext));
1045 // ------------------------------------------------------------------------------
1046 void get4byte(sbyte *bytep)
1051 for (i=0; i<NDL; i++) {
1052 curtext = strtok(NULL, space);
1053 bytep[i] = atoi(curtext);
1057 // ------------------------------------------------------------------------------
1058 // Convert field of view from an angle in 0..360 to cosine.
1059 void adjust_field_of_view(fix *fovp)
1066 for (i=0; i<NDL; i++) {
1067 ff = - f2fl(fovp[i]);
1069 mprintf((1, "Warning: Bogus field of view (%7.3f). Must be in 0..179.\n", ff));
1074 fix_sincos(tt, &temp, &fovp[i]);
1078 void clear_to_end_of_line(void)
1080 arg = strtok( NULL, space );
1082 arg = strtok( NULL, space );
1085 void bm_read_sound()
1090 sound_num = get_int();
1091 alt_sound_num = get_int();
1093 if ( sound_num>=MAX_SOUNDS )
1094 Error( "Too many sound files.\n" );
1096 if (sound_num >= num_sounds)
1097 num_sounds = sound_num+1;
1099 if (Sounds[sound_num] != 255)
1100 Error("Sound num %d already used, bitmaps.tbl, line %d\n",sound_num,linenum);
1102 arg = strtok(NULL, space);
1104 Sounds[sound_num] = ds_load(arg);
1106 if ( alt_sound_num == 0 )
1107 AltSounds[sound_num] = sound_num;
1108 else if (alt_sound_num < 0 )
1109 AltSounds[sound_num] = 255;
1111 AltSounds[sound_num] = alt_sound_num;
1113 if (Sounds[sound_num] == 255)
1114 Error("Can't load soundfile <%s>",arg);
1117 // ------------------------------------------------------------------------------
1118 void bm_read_robot_ai()
1120 char *robotnum_text;
1124 robotnum_text = strtok(NULL, space);
1125 robotnum = atoi(robotnum_text);
1126 Assert(robotnum < MAX_ROBOT_TYPES);
1127 robptr = &Robot_info[robotnum];
1129 Assert(robotnum == Num_robot_ais); //make sure valid number
1132 if (Registered_only) {
1134 clear_to_end_of_line();
1141 get4fix(robptr->field_of_view);
1142 get4fix(robptr->firing_wait);
1143 get4fix(robptr->firing_wait2);
1144 get4byte(robptr->rapidfire_count);
1145 get4fix(robptr->turn_time);
1146 // get4fix(robptr->fire_power);
1147 // get4fix(robptr->shield);
1148 get4fix(robptr->max_speed);
1149 get4fix(robptr->circle_distance);
1150 get4byte(robptr->evade_speed);
1152 robptr->always_0xabcd = 0xabcd;
1154 adjust_field_of_view(robptr->field_of_view);
1158 // ----------------------------------------------------------------------------------------------
1159 //this will load a bitmap for a polygon models. it puts the bitmap into
1160 //the array ObjBitmaps[], and also deals with animating bitmaps
1161 //returns a pointer to the bitmap
1162 grs_bitmap *load_polymodel_bitmap(char *name)
1164 Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
1166 // Assert( N_ObjBitmaps == N_ObjBitmapPtrs );
1168 if (name[0] == '%') { //an animating bitmap!
1171 eclip_num = atoi(name+1);
1173 if (Effects[eclip_num].changing_object_texture == -1) { //first time referenced
1174 Effects[eclip_num].changing_object_texture = N_ObjBitmaps;
1175 ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps;
1178 ObjBitmapPtrs[N_ObjBitmapPtrs++] = Effects[eclip_num].changing_object_texture;
1180 Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
1181 Assert(N_ObjBitmapPtrs < MAX_OBJ_BITMAPS);
1185 ObjBitmaps[N_ObjBitmaps] = bm_load_sub(name);
1186 if (GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_w!=64 || GameBitmaps[ObjBitmaps[N_ObjBitmaps].index].bm_h!=64)
1187 Error("Bitmap <%s> is not 64x64",name);
1188 ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps;
1190 Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS);
1191 Assert(N_ObjBitmapPtrs < MAX_OBJ_BITMAPS);
1192 return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index];
1196 #define MAX_MODEL_VARIANTS 4
1198 // ------------------------------------------------------------------------------
1199 void bm_read_robot()
1201 char *model_name[MAX_MODEL_VARIANTS];
1203 int first_bitmap_num[MAX_MODEL_VARIANTS];
1205 int exp1_vclip_num=-1;
1206 int exp1_sound_num=-1;
1207 int exp2_vclip_num=-1;
1208 int exp2_sound_num=-1;
1209 fix lighting = F1_0/2; // Default
1210 fix strength = F1_0*10; // Default strength
1213 short weapon_type = 0, weapon_type2 = -1;
1215 char name[ROBOT_NAME_LENGTH];
1216 int contains_count=0, contains_id=0, contains_prob=0, contains_type=0, behavior=AIB_NORMAL;
1217 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;
1218 fix glow=0, aim=F1_0;
1219 int deathroll_sound = SOUND_BOSS_SHARE_DIE; //default
1220 int score_value=1000;
1221 int cloak_type=0; // Default = this robot does not cloak
1222 int attack_type=0; // Default = this robot attacks by firing (1=lunge)
1223 int boss_flag=0; // Default = robot is not a boss.
1224 int see_sound = ROBOT_SEE_SOUND_DEFAULT;
1225 int attack_sound = ROBOT_ATTACK_SOUND_DEFAULT;
1226 int claw_sound = ROBOT_CLAW_SOUND_DEFAULT;
1227 int taunt_sound = ROBOT_SEE_SOUND_DEFAULT;
1230 Assert(N_robot_types < MAX_ROBOT_TYPES);
1233 if (Registered_only) {
1234 Robot_info[N_robot_types].model_num = -1;
1236 Assert(N_robot_types < MAX_ROBOT_TYPES);
1237 clear_to_end_of_line();
1242 model_name[0] = strtok( NULL, space );
1243 first_bitmap_num[0] = N_ObjBitmapPtrs;
1248 arg = strtok( NULL, space );
1250 equal_ptr = strchr( arg, '=' );
1254 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1255 if (!stricmp( arg, "exp1_vclip" )) {
1256 exp1_vclip_num = atoi(equal_ptr);
1257 } else if (!stricmp( arg, "exp2_vclip" )) {
1258 exp2_vclip_num = atoi(equal_ptr);
1259 } else if (!stricmp( arg, "exp1_sound" )) {
1260 exp1_sound_num = atoi(equal_ptr);
1261 } else if (!stricmp( arg, "exp2_sound" )) {
1262 exp2_sound_num = atoi(equal_ptr);
1263 } else if (!stricmp( arg, "lighting" )) {
1264 lighting = fl2f(atof(equal_ptr));
1265 if ( (lighting < 0) || (lighting > F1_0 )) {
1266 mprintf( (1, "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)));
1267 Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting));
1269 } else if (!stricmp( arg, "weapon_type" )) {
1270 weapon_type = atoi(equal_ptr);
1271 } else if (!stricmp( arg, "weapon_type2" )) {
1272 weapon_type2 = atoi(equal_ptr);
1273 } else if (!stricmp( arg, "strength" )) {
1274 strength = i2f(atoi(equal_ptr));
1275 } else if (!stricmp( arg, "mass" )) {
1276 mass = fl2f(atof(equal_ptr));
1277 } else if (!stricmp( arg, "drag" )) {
1278 drag = fl2f(atof(equal_ptr));
1279 } else if (!stricmp( arg, "contains_id" )) {
1280 contains_id = atoi(equal_ptr);
1281 } else if (!stricmp( arg, "contains_type" )) {
1282 contains_type = atoi(equal_ptr);
1283 } else if (!stricmp( arg, "contains_count" )) {
1284 contains_count = atoi(equal_ptr);
1285 } else if (!stricmp( arg, "companion" )) {
1286 companion = atoi(equal_ptr);
1287 } else if (!stricmp( arg, "badass" )) {
1288 badass = atoi(equal_ptr);
1289 } else if (!stricmp( arg, "lightcast" )) {
1290 lightcast = atoi(equal_ptr);
1291 } else if (!stricmp( arg, "glow" )) {
1292 glow = fl2f(atof(equal_ptr));
1293 } else if (!stricmp( arg, "death_roll" )) {
1294 death_roll = atoi(equal_ptr);
1295 } else if (!stricmp( arg, "deathroll_sound" )) {
1296 deathroll_sound = atoi(equal_ptr);
1297 } else if (!stricmp( arg, "thief" )) {
1298 thief = atoi(equal_ptr);
1299 } else if (!stricmp( arg, "kamikaze" )) {
1300 kamikaze = atoi(equal_ptr);
1301 } else if (!stricmp( arg, "pursuit" )) {
1302 pursuit = atoi(equal_ptr);
1303 } else if (!stricmp( arg, "smart_blobs" )) {
1304 smart_blobs = atoi(equal_ptr);
1305 } else if (!stricmp( arg, "energy_blobs" )) {
1306 energy_blobs = atoi(equal_ptr);
1307 } else if (!stricmp( arg, "energy_drain" )) {
1308 energy_drain = atoi(equal_ptr);
1309 } else if (!stricmp( arg, "contains_prob" )) {
1310 contains_prob = atoi(equal_ptr);
1311 } else if (!stricmp( arg, "cloak_type" )) {
1312 cloak_type = atoi(equal_ptr);
1313 } else if (!stricmp( arg, "attack_type" )) {
1314 attack_type = atoi(equal_ptr);
1315 } else if (!stricmp( arg, "boss" )) {
1316 boss_flag = atoi(equal_ptr);
1317 } else if (!stricmp( arg, "score_value" )) {
1318 score_value = atoi(equal_ptr);
1319 } else if (!stricmp( arg, "see_sound" )) {
1320 see_sound = atoi(equal_ptr);
1321 } else if (!stricmp( arg, "attack_sound" )) {
1322 attack_sound = atoi(equal_ptr);
1323 } else if (!stricmp( arg, "claw_sound" )) {
1324 claw_sound = atoi(equal_ptr);
1325 } else if (!stricmp( arg, "taunt_sound" )) {
1326 taunt_sound = atoi(equal_ptr);
1327 } else if (!stricmp( arg, "aim" )) {
1328 aim = fl2f(atof(equal_ptr));
1329 } else if (!stricmp( arg, "big_radius" )) {
1330 if (atoi(equal_ptr))
1331 flags |= RIF_BIG_RADIUS;
1332 } else if (!stricmp( arg, "behavior" )) {
1333 if (!stricmp(equal_ptr, "STILL"))
1334 behavior = AIB_STILL;
1335 else if (!stricmp(equal_ptr, "NORMAL"))
1336 behavior = AIB_NORMAL;
1337 else if (!stricmp(equal_ptr, "BEHIND"))
1338 behavior = AIB_BEHIND;
1339 else if (!stricmp(equal_ptr, "RUN_FROM"))
1340 behavior = AIB_RUN_FROM;
1341 else if (!stricmp(equal_ptr, "SNIPE"))
1342 behavior = AIB_SNIPE;
1343 else if (!stricmp(equal_ptr, "STATION"))
1344 behavior = AIB_STATION;
1345 else if (!stricmp(equal_ptr, "FOLLOW"))
1346 behavior = AIB_FOLLOW;
1348 Int3(); // Error. Illegal behavior type for current robot.
1349 } else if (!stricmp( arg, "name" )) {
1350 Assert(strlen(equal_ptr) < ROBOT_NAME_LENGTH); // Oops, name too long.
1351 strcpy(name, &equal_ptr[1]);
1352 name[strlen(name)-1] = 0;
1353 } else if (!stricmp( arg, "simple_model" )) {
1354 model_name[n_models] = equal_ptr;
1355 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1357 Assert(n_models < MAX_MODEL_VARIANTS);
1360 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1362 } else { // Must be a texture specification...
1363 load_polymodel_bitmap(arg);
1365 arg = strtok( NULL, space );
1368 //clear out anim info
1369 for (g=0;g<MAX_GUNS+1;g++)
1370 for (s=0;s<N_ANIM_STATES;s++)
1371 Robot_info[N_robot_types].anim_states[g][s].n_joints = 0; //inialize to zero
1373 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1375 for (i=0;i<n_models;i++) {
1377 int model_num,last_model_num=0;
1379 n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
1381 model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],(i==0)?&Robot_info[N_robot_types]:NULL);
1384 Robot_info[N_robot_types].model_num = model_num;
1386 Polygon_models[last_model_num].simpler_model = model_num+1;
1388 last_model_num = model_num;
1391 if ((glow > i2f(15)) || (glow < 0) || (glow != 0 && glow < 0x1000)) {
1392 mprintf((0,"Invalid glow value %x for robot %d\n",glow,N_robot_types));
1396 Robot_info[N_robot_types].exp1_vclip_num = exp1_vclip_num;
1397 Robot_info[N_robot_types].exp2_vclip_num = exp2_vclip_num;
1398 Robot_info[N_robot_types].exp1_sound_num = exp1_sound_num;
1399 Robot_info[N_robot_types].exp2_sound_num = exp2_sound_num;
1400 Robot_info[N_robot_types].lighting = lighting;
1401 Robot_info[N_robot_types].weapon_type = weapon_type;
1402 Robot_info[N_robot_types].weapon_type2 = weapon_type2;
1403 Robot_info[N_robot_types].strength = strength;
1404 Robot_info[N_robot_types].mass = mass;
1405 Robot_info[N_robot_types].drag = drag;
1406 Robot_info[N_robot_types].cloak_type = cloak_type;
1407 Robot_info[N_robot_types].attack_type = attack_type;
1408 Robot_info[N_robot_types].boss_flag = boss_flag;
1410 Robot_info[N_robot_types].contains_id = contains_id;
1411 Robot_info[N_robot_types].contains_count = contains_count;
1412 Robot_info[N_robot_types].contains_prob = contains_prob;
1413 Robot_info[N_robot_types].companion = companion;
1414 Robot_info[N_robot_types].badass = badass;
1415 Robot_info[N_robot_types].lightcast = lightcast;
1416 Robot_info[N_robot_types].glow = (glow>>12); //convert to 4:4
1417 Robot_info[N_robot_types].death_roll = death_roll;
1418 Robot_info[N_robot_types].deathroll_sound = deathroll_sound;
1419 Robot_info[N_robot_types].thief = thief;
1420 Robot_info[N_robot_types].flags = flags;
1421 Robot_info[N_robot_types].kamikaze = kamikaze;
1422 Robot_info[N_robot_types].pursuit = pursuit;
1423 Robot_info[N_robot_types].smart_blobs = smart_blobs;
1424 Robot_info[N_robot_types].energy_blobs = energy_blobs;
1425 Robot_info[N_robot_types].energy_drain = energy_drain;
1426 Robot_info[N_robot_types].score_value = score_value;
1427 Robot_info[N_robot_types].see_sound = see_sound;
1428 Robot_info[N_robot_types].attack_sound = attack_sound;
1429 Robot_info[N_robot_types].claw_sound = claw_sound;
1430 Robot_info[N_robot_types].taunt_sound = taunt_sound;
1431 Robot_info[N_robot_types].behavior = behavior; // Default behavior for this robot, if coming out of matcen.
1432 Robot_info[N_robot_types].aim = min(f2i(aim*255), 255); // how well this robot type can aim. 255=perfect
1435 Robot_info[N_robot_types].contains_type = OBJ_ROBOT;
1437 Robot_info[N_robot_types].contains_type = OBJ_POWERUP;
1439 strcpy(Robot_names[N_robot_types], name);
1443 Assert(N_robot_types < MAX_ROBOT_TYPES);
1448 //read a reactor model
1449 void bm_read_reactor()
1451 char *model_name, *model_name_dead=NULL;
1452 int first_bitmap_num, first_bitmap_num_dead=0, n_normal_bitmaps;
1455 short explosion_vclip_num = -1;
1456 short explosion_sound_num = SOUND_ROBOT_DESTROYED;
1457 fix lighting = F1_0/2; // Default
1461 Assert(Num_reactors < MAX_REACTORS);
1464 if (Registered_only) {
1466 clear_to_end_of_line();
1471 model_name = strtok( NULL, space );
1475 arg = strtok( NULL, space );
1476 first_bitmap_num = N_ObjBitmapPtrs;
1480 equal_ptr = strchr( arg, '=' );
1486 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1488 if (!stricmp( arg, "exp_vclip" )) {
1489 explosion_vclip_num = atoi(equal_ptr);
1490 } else if (!stricmp( arg, "dead_pof" )) {
1491 model_name_dead = equal_ptr;
1492 first_bitmap_num_dead=N_ObjBitmapPtrs;
1493 } else if (!stricmp( arg, "exp_sound" )) {
1494 explosion_sound_num = atoi(equal_ptr);
1495 } else if (!stricmp( arg, "lighting" )) {
1496 lighting = fl2f(atof(equal_ptr));
1497 if ( (lighting < 0) || (lighting > F1_0 )) {
1498 mprintf( (1, "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)));
1499 Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting));
1501 } else if (!stricmp( arg, "strength" )) {
1502 strength = fl2f(atof(equal_ptr));
1505 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1507 } else { // Must be a texture specification...
1508 load_polymodel_bitmap(arg);
1510 arg = strtok( NULL, space );
1513 if ( model_name_dead )
1514 n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num;
1516 n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num;
1518 model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL);
1520 if ( model_name_dead )
1521 Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL);
1523 Dead_modelnums[model_num] = -1;
1526 Error("No object type specfied for object in BITMAPS.TBL on line %d\n",linenum);
1528 Reactors[Num_reactors].model_num = model_num;
1529 Reactors[Num_reactors].n_guns = read_model_guns(model_name,Reactors[Num_reactors].gun_points,Reactors[Num_reactors].gun_dirs,NULL);
1534 //read the marker object
1535 void bm_read_marker()
1538 int first_bitmap_num, n_normal_bitmaps;
1541 model_name = strtok( NULL, space );
1545 arg = strtok( NULL, space );
1546 first_bitmap_num = N_ObjBitmapPtrs;
1550 equal_ptr = strchr( arg, '=' );
1556 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1557 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1560 } else { // Must be a texture specification...
1561 load_polymodel_bitmap(arg);
1563 arg = strtok( NULL, space );
1566 n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num;
1568 Marker_model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL);
1572 //read the exit model
1573 void bm_read_exitmodel()
1575 char *model_name, *model_name_dead=NULL;
1576 int first_bitmap_num, first_bitmap_num_dead, n_normal_bitmaps;
1580 model_name = strtok( NULL, space );
1584 arg = strtok( NULL, space );
1585 first_bitmap_num = N_ObjBitmapPtrs;
1589 equal_ptr = strchr( arg, '=' );
1595 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1597 if (!stricmp( arg, "dead_pof" )) {
1598 model_name_dead = equal_ptr;
1599 first_bitmap_num_dead=N_ObjBitmapPtrs;
1602 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1604 } else { // Must be a texture specification...
1605 load_polymodel_bitmap(arg);
1607 arg = strtok( NULL, space );
1610 if ( model_name_dead )
1611 n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num;
1613 n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num;
1615 model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL);
1617 if ( model_name_dead )
1618 Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL);
1620 Dead_modelnums[model_num] = -1;
1622 exit_modelnum = model_num;
1623 destroyed_exit_modelnum = Dead_modelnums[model_num];
1628 void bm_read_player_ship()
1630 char *model_name_dying=NULL;
1631 char *model_name[MAX_MODEL_VARIANTS];
1633 int first_bitmap_num[MAX_MODEL_VARIANTS];
1636 int last_multi_bitmap_num=-1;
1641 arg = strtok( NULL, space );
1643 Player_ship->mass = Player_ship->drag = 0; //stupid defaults
1644 Player_ship->expl_vclip_num = -1;
1648 equal_ptr = strchr( arg, '=' );
1655 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1657 if (!stricmp( arg, "model" )) {
1658 Assert(n_models==0);
1659 model_name[0] = equal_ptr;
1660 first_bitmap_num[0] = N_ObjBitmapPtrs;
1662 } else if (!stricmp( arg, "simple_model" )) {
1663 model_name[n_models] = equal_ptr;
1664 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1666 Assert(n_models < MAX_MODEL_VARIANTS);
1668 if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1)
1669 last_multi_bitmap_num=N_ObjBitmapPtrs;
1671 else if (!stricmp( arg, "mass" ))
1672 Player_ship->mass = fl2f(atof(equal_ptr));
1673 else if (!stricmp( arg, "drag" ))
1674 Player_ship->drag = fl2f(atof(equal_ptr));
1675 // else if (!stricmp( arg, "low_thrust" ))
1676 // Player_ship->low_thrust = fl2f(atof(equal_ptr));
1677 else if (!stricmp( arg, "max_thrust" ))
1678 Player_ship->max_thrust = fl2f(atof(equal_ptr));
1679 else if (!stricmp( arg, "reverse_thrust" ))
1680 Player_ship->reverse_thrust = fl2f(atof(equal_ptr));
1681 else if (!stricmp( arg, "brakes" ))
1682 Player_ship->brakes = fl2f(atof(equal_ptr));
1683 else if (!stricmp( arg, "wiggle" ))
1684 Player_ship->wiggle = fl2f(atof(equal_ptr));
1685 else if (!stricmp( arg, "max_rotthrust" ))
1686 Player_ship->max_rotthrust = fl2f(atof(equal_ptr));
1687 else if (!stricmp( arg, "dying_pof" ))
1688 model_name_dying = equal_ptr;
1689 else if (!stricmp( arg, "expl_vclip_num" ))
1690 Player_ship->expl_vclip_num=atoi(equal_ptr);
1693 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
1696 else if (!stricmp( arg, "multi_textures" )) {
1698 First_multi_bitmap_num = N_ObjBitmapPtrs;
1699 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1702 else // Must be a texture specification...
1704 load_polymodel_bitmap(arg);
1706 arg = strtok( NULL, space );
1709 Assert(model_name != NULL);
1711 if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1)
1712 last_multi_bitmap_num=N_ObjBitmapPtrs;
1714 if (First_multi_bitmap_num==-1)
1715 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1718 Assert(last_multi_bitmap_num-First_multi_bitmap_num == (MAX_NUM_NET_PLAYERS-1)*2);
1721 for (i=0;i<n_models;i++) {
1723 int model_num,last_model_num=0;
1725 n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
1727 model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],(i==0)?&ri:NULL);
1730 Player_ship->model_num = model_num;
1732 Polygon_models[last_model_num].simpler_model = model_num+1;
1734 last_model_num = model_num;
1737 if ( model_name_dying ) {
1739 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);
1742 Assert(ri.n_guns == N_PLAYER_GUNS);
1744 //calc player gun positions
1750 int mn; //submodel number
1754 pm = &Polygon_models[Player_ship->model_num];
1756 for (gun_num=0;gun_num<r->n_guns;gun_num++) {
1758 pnt = r->gun_points[gun_num];
1759 mn = r->gun_submodels[gun_num];
1761 //instance up the tree for this gun
1763 vm_vec_add2(&pnt,&pm->submodel_offsets[mn]);
1764 mn = pm->submodel_parents[mn];
1767 Player_ship->gun_points[gun_num] = pnt;
1775 void bm_read_some_file()
1780 Error("Trying to read bitmap <%s> with bm_flag==BM_NONE on line %d of BITMAPS.TBL",arg,linenum);
1783 bitmap_index bitmap;
1784 bitmap = bm_load_sub(arg);
1785 Assert( Num_cockpits < N_COCKPIT_BITMAPS );
1786 cockpit_bitmap[Num_cockpits++] = bitmap;
1787 //bm_flag = BM_NONE;
1795 case BM_GAUGES_HIRES:
1796 bm_read_gauges_hires();
1812 bitmap_index bitmap;
1813 bitmap = bm_load_sub(arg);
1814 Assert(tmap_count < MAX_TEXTURES);
1815 TmapList[tmap_count++] = texture_count;
1816 Textures[texture_count] = bitmap;
1817 set_texture_name( arg );
1818 Assert(texture_count < MAX_TEXTURES);
1820 NumTextures = texture_count;
1830 Error("Trying to read bitmap <%s> with unknown bm_flag <%x> on line %d of BITMAPS.TBL",arg,bm_flag,linenum);
1833 // ------------------------------------------------------------------------------
1834 // If unused_flag is set, then this is just a placeholder. Don't actually reference vclips or load bbms.
1835 void bm_read_weapon(int unused_flag)
1840 char *pof_file_inner=NULL;
1841 char *model_name[MAX_MODEL_VARIANTS];
1842 int first_bitmap_num[MAX_MODEL_VARIANTS];
1843 int lighted; //flag for whether is a texture is lighted
1845 Assert(N_weapon_types < MAX_WEAPON_TYPES);
1849 Assert(N_weapon_types <= MAX_WEAPON_TYPES);
1852 clear_to_end_of_line();
1857 if (Registered_only) {
1858 clear_to_end_of_line();
1863 // Initialize weapon array
1864 Weapon_info[n].render_type = WEAPON_RENDER_NONE; // 0=laser, 1=blob, 2=object
1865 Weapon_info[n].bitmap.index = 0;
1866 Weapon_info[n].model_num = -1;
1867 Weapon_info[n].model_num_inner = -1;
1868 Weapon_info[n].blob_size = 0x1000; // size of blob
1869 Weapon_info[n].flash_vclip = -1;
1870 Weapon_info[n].flash_sound = SOUND_LASER_FIRED;
1871 Weapon_info[n].flash_size = 0;
1872 Weapon_info[n].robot_hit_vclip = -1;
1873 Weapon_info[n].robot_hit_sound = -1;
1874 Weapon_info[n].wall_hit_vclip = -1;
1875 Weapon_info[n].wall_hit_sound = -1;
1876 Weapon_info[n].impact_size = 0;
1877 for (i=0; i<NDL; i++) {
1878 Weapon_info[n].strength[i] = F1_0;
1879 Weapon_info[n].speed[i] = F1_0*10;
1881 Weapon_info[n].mass = F1_0;
1882 Weapon_info[n].thrust = 0;
1883 Weapon_info[n].drag = 0;
1884 Weapon_info[n].persistent = 0;
1886 Weapon_info[n].energy_usage = 0; // How much fuel is consumed to fire this weapon.
1887 Weapon_info[n].ammo_usage = 0; // How many units of ammunition it uses.
1888 Weapon_info[n].fire_wait = F1_0/4; // Time until this weapon can be fired again.
1889 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.
1890 Weapon_info[n].damage_radius = 0; // Radius of damage for missiles, not lasers. Does damage to objects within this radius of hit point.
1891 //--01/19/95, mk-- Weapon_info[n].damage_force = 0; // Force (movement) due to explosion
1892 Weapon_info[n].destroyable = 1; // Weapons default to destroyable
1893 Weapon_info[n].matter = 0; // Weapons default to not being constructed of matter (they are energy!)
1894 Weapon_info[n].bounce = 0; // Weapons default to not bouncing off walls
1896 Weapon_info[n].flags = 0;
1898 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.
1900 Weapon_info[n].po_len_to_width_ratio = F1_0*10;
1902 Weapon_info[n].picture.index = 0;
1903 Weapon_info[n].hires_picture.index = 0;
1904 Weapon_info[n].homing_flag = 0;
1906 Weapon_info[n].flash = 0;
1907 Weapon_info[n].multi_damage_scale = F1_0;
1908 Weapon_info[n].afterburner_size = 0;
1909 Weapon_info[n].children = -1;
1911 // Process arguments
1912 arg = strtok( NULL, space );
1914 lighted = 1; //assume first texture is lighted
1916 Weapon_info[n].speedvar = 128;
1919 equal_ptr = strchr( arg, '=' );
1923 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
1924 if (!stricmp( arg, "laser_bmp" )) {
1925 // Load bitmap with name equal_ptr
1927 Weapon_info[n].bitmap = bm_load_sub(equal_ptr); //load_polymodel_bitmap(equal_ptr);
1928 Weapon_info[n].render_type = WEAPON_RENDER_LASER;
1930 } else if (!stricmp( arg, "blob_bmp" )) {
1931 // Load bitmap with name equal_ptr
1933 Weapon_info[n].bitmap = bm_load_sub(equal_ptr); //load_polymodel_bitmap(equal_ptr);
1934 Weapon_info[n].render_type = WEAPON_RENDER_BLOB;
1936 } else if (!stricmp( arg, "weapon_vclip" )) {
1937 // Set vclip to play for this weapon.
1938 Weapon_info[n].bitmap.index = 0;
1939 Weapon_info[n].render_type = WEAPON_RENDER_VCLIP;
1940 Weapon_info[n].weapon_vclip = atoi(equal_ptr);
1942 } else if (!stricmp( arg, "none_bmp" )) {
1943 Weapon_info[n].bitmap = bm_load_sub(equal_ptr);
1944 Weapon_info[n].render_type = WEAPON_RENDER_NONE;
1946 } else if (!stricmp( arg, "weapon_pof" )) {
1948 Assert(n_models==0);
1949 model_name[0] = equal_ptr;
1950 first_bitmap_num[0] = N_ObjBitmapPtrs;
1952 } else if (!stricmp( arg, "simple_model" )) {
1953 model_name[n_models] = equal_ptr;
1954 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
1956 Assert(n_models < MAX_MODEL_VARIANTS);
1957 } else if (!stricmp( arg, "weapon_pof_inner" )) {
1959 pof_file_inner = equal_ptr;
1960 } else if (!stricmp( arg, "strength" )) {
1961 for (i=0; i<NDL-1; i++) {
1962 Weapon_info[n].strength[i] = fl2f(atof(equal_ptr));
1963 equal_ptr = strtok(NULL, space);
1965 Weapon_info[n].strength[i] = i2f(atoi(equal_ptr));
1966 } else if (!stricmp( arg, "mass" )) {
1967 Weapon_info[n].mass = fl2f(atof(equal_ptr));
1968 } else if (!stricmp( arg, "drag" )) {
1969 Weapon_info[n].drag = fl2f(atof(equal_ptr));
1970 } else if (!stricmp( arg, "thrust" )) {
1971 Weapon_info[n].thrust = fl2f(atof(equal_ptr));
1972 } else if (!stricmp( arg, "matter" )) {
1973 Weapon_info[n].matter = atoi(equal_ptr);
1974 } else if (!stricmp( arg, "bounce" )) {
1975 Weapon_info[n].bounce = atoi(equal_ptr);
1976 } else if (!stricmp( arg, "speed" )) {
1977 for (i=0; i<NDL-1; i++) {
1978 Weapon_info[n].speed[i] = i2f(atoi(equal_ptr));
1979 equal_ptr = strtok(NULL, space);
1981 Weapon_info[n].speed[i] = i2f(atoi(equal_ptr));
1982 } else if (!stricmp( arg, "speedvar" )) {
1983 Weapon_info[n].speedvar = (atoi(equal_ptr) * 128) / 100;
1984 } else if (!stricmp( arg, "flash_vclip" )) {
1985 Weapon_info[n].flash_vclip = atoi(equal_ptr);
1986 } else if (!stricmp( arg, "flash_sound" )) {
1987 Weapon_info[n].flash_sound = atoi(equal_ptr);
1988 } else if (!stricmp( arg, "flash_size" )) {
1989 Weapon_info[n].flash_size = fl2f(atof(equal_ptr));
1990 } else if (!stricmp( arg, "blob_size" )) {
1991 Weapon_info[n].blob_size = fl2f(atof(equal_ptr));
1992 } else if (!stricmp( arg, "robot_hit_vclip" )) {
1993 Weapon_info[n].robot_hit_vclip = atoi(equal_ptr);
1994 } else if (!stricmp( arg, "robot_hit_sound" )) {
1995 Weapon_info[n].robot_hit_sound = atoi(equal_ptr);
1996 } else if (!stricmp( arg, "wall_hit_vclip" )) {
1997 Weapon_info[n].wall_hit_vclip = atoi(equal_ptr);
1998 } else if (!stricmp( arg, "wall_hit_sound" )) {
1999 Weapon_info[n].wall_hit_sound = atoi(equal_ptr);
2000 } else if (!stricmp( arg, "impact_size" )) {
2001 Weapon_info[n].impact_size = fl2f(atof(equal_ptr));
2002 } else if (!stricmp( arg, "lighted" )) {
2003 lighted = atoi(equal_ptr);
2004 } else if (!stricmp( arg, "lw_ratio" )) {
2005 Weapon_info[n].po_len_to_width_ratio = fl2f(atof(equal_ptr));
2006 } else if (!stricmp( arg, "lightcast" )) {
2007 Weapon_info[n].light = fl2f(atof(equal_ptr));
2008 } else if (!stricmp( arg, "persistent" )) {
2009 Weapon_info[n].persistent = atoi(equal_ptr);
2010 } else if (!stricmp(arg, "energy_usage" )) {
2011 Weapon_info[n].energy_usage = fl2f(atof(equal_ptr));
2012 } else if (!stricmp(arg, "ammo_usage" )) {
2013 Weapon_info[n].ammo_usage = atoi(equal_ptr);
2014 } else if (!stricmp(arg, "fire_wait" )) {
2015 Weapon_info[n].fire_wait = fl2f(atof(equal_ptr));
2016 } else if (!stricmp(arg, "fire_count" )) {
2017 Weapon_info[n].fire_count = atoi(equal_ptr);
2018 } else if (!stricmp(arg, "damage_radius" )) {
2019 Weapon_info[n].damage_radius = fl2f(atof(equal_ptr));
2020 //--01/19/95, mk-- } else if (!stricmp(arg, "damage_force" )) {
2021 //--01/19/95, mk-- Weapon_info[n].damage_force = fl2f(atof(equal_ptr));
2022 } else if (!stricmp(arg, "lifetime" )) {
2023 Weapon_info[n].lifetime = fl2f(atof(equal_ptr));
2024 } else if (!stricmp(arg, "destroyable" )) {
2025 Weapon_info[n].destroyable = atoi(equal_ptr);
2026 } else if (!stricmp(arg, "picture" )) {
2027 Weapon_info[n].picture = bm_load_sub(equal_ptr);
2028 } else if (!stricmp(arg, "hires_picture" )) {
2029 Weapon_info[n].hires_picture = bm_load_sub(equal_ptr);
2030 } else if (!stricmp(arg, "homing" )) {
2031 Weapon_info[n].homing_flag = !!atoi(equal_ptr);
2032 } else if (!stricmp(arg, "flash" )) {
2033 Weapon_info[n].flash = atoi(equal_ptr);
2034 } else if (!stricmp(arg, "multi_damage_scale" )) {
2035 Weapon_info[n].multi_damage_scale = fl2f(atof(equal_ptr));
2036 } else if (!stricmp(arg, "afterburner_size" )) {
2037 Weapon_info[n].afterburner_size = f2i(16*fl2f(atof(equal_ptr)));
2038 } else if (!stricmp(arg, "children" )) {
2039 Weapon_info[n].children = atoi(equal_ptr);
2040 } else if (!stricmp(arg, "placable" )) {
2041 if (atoi(equal_ptr)) {
2042 Weapon_info[n].flags |= WIF_PLACABLE;
2046 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
2048 } else { // Must be a texture specification...
2051 bm = load_polymodel_bitmap(arg);
2053 bm->bm_flags |= BM_FLAG_NO_LIGHTING;
2055 lighted = 1; //default for next bitmap is lighted
2057 arg = strtok( NULL, space );
2060 first_bitmap_num[n_models] = N_ObjBitmapPtrs;
2062 for (i=0;i<n_models;i++) {
2064 int model_num,last_model_num=0;
2066 n_textures = first_bitmap_num[i+1] - first_bitmap_num[i];
2068 model_num = load_polygon_model(model_name[i],n_textures,first_bitmap_num[i],NULL);
2071 Weapon_info[n].render_type = WEAPON_RENDER_POLYMODEL;
2072 Weapon_info[n].model_num = model_num;
2075 Polygon_models[last_model_num].simpler_model = model_num+1;
2077 last_model_num = model_num;
2080 if ( pof_file_inner ) {
2082 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);
2085 if ((Weapon_info[n].ammo_usage == 0) && (Weapon_info[n].energy_usage == 0))
2086 mprintf((1, "Warning: Weapon %i has ammo and energy usage of 0.\n", n));
2088 // -- render type of none is now legal -- Assert( Weapon_info[n].render_type != WEAPON_RENDER_NONE );
2095 // ------------------------------------------------------------------------------
2096 #define DEFAULT_POWERUP_SIZE i2f(3)
2098 void bm_read_powerup(int unused_flag)
2103 Assert(N_powerup_types < MAX_POWERUP_TYPES);
2105 n = N_powerup_types;
2109 clear_to_end_of_line();
2113 // Initialize powerup array
2114 Powerup_info[n].light = F1_0/3; // Default lighting value.
2115 Powerup_info[n].vclip_num = -1;
2116 Powerup_info[n].hit_sound = -1;
2117 Powerup_info[n].size = DEFAULT_POWERUP_SIZE;
2118 Powerup_names[n][0] = 0;
2120 // Process arguments
2121 arg = strtok( NULL, space );
2124 equal_ptr = strchr( arg, '=' );
2128 // if we have john=cool, arg is 'john' and equal_ptr is 'cool'
2129 if (!stricmp( arg, "vclip_num" )) {
2130 Powerup_info[n].vclip_num = atoi(equal_ptr);
2131 } else if (!stricmp( arg, "light" )) {
2132 Powerup_info[n].light = fl2f(atof(equal_ptr));
2133 } else if (!stricmp( arg, "hit_sound" )) {
2134 Powerup_info[n].hit_sound = atoi(equal_ptr);
2135 } else if (!stricmp( arg, "name" )) {
2136 Assert(strlen(equal_ptr) < POWERUP_NAME_LENGTH); // Oops, name too long.
2137 strcpy(Powerup_names[n], &equal_ptr[1]);
2138 Powerup_names[n][strlen(Powerup_names[n])-1] = 0;
2139 } else if (!stricmp( arg, "size" )) {
2140 Powerup_info[n].size = fl2f(atof(equal_ptr));
2143 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
2145 } else { // Must be a texture specification...
2147 mprintf( (1, "Invalid argument, %s in bitmaps.tbl\n", arg ));
2149 arg = strtok( NULL, space );
2153 void bm_read_hostage()
2158 Assert(N_hostage_types < MAX_HOSTAGE_TYPES);
2160 n = N_hostage_types;
2163 // Process arguments
2164 arg = strtok( NULL, space );
2167 equal_ptr = strchr( arg, '=' );
2172 if (!stricmp( arg, "vclip_num" ))
2174 Hostage_vclip_num[n] = atoi(equal_ptr);
2178 mprintf( (1, "Invalid parameter, %s=%s in bitmaps.tbl\n", arg, equal_ptr ));
2183 mprintf( (1, "Invalid argument, %s in bitmaps.tbl at line %d\n", arg, linenum ));
2185 arg = strtok( NULL, space );
2189 //these values are the number of each item in the release of d2
2190 //extra items added after the release get written in an additional hamfile
2191 #define N_D2_ROBOT_TYPES 66
2192 #define N_D2_ROBOT_JOINTS 1145
2193 #define N_D2_POLYGON_MODELS 166
2194 #define N_D2_OBJBITMAPS 422
2195 #define N_D2_OBJBITMAPPTRS 502
2196 #define N_D2_WEAPON_TYPES 62
2198 void bm_write_all(FILE *fp)
2204 tfile = fopen("hamfile.lst","wt");
2206 t = NumTextures-1; //don't save bogus texture
2207 fwrite( &t, sizeof(int), 1, fp );
2208 fwrite( Textures, sizeof(bitmap_index), t, fp );
2210 fwrite( &TmapInfo[i], sizeof(*TmapInfo)-sizeof(TmapInfo->filename)-sizeof(TmapInfo->pad2), 1, fp );
2211 fprintf(tfile, "NumTextures = %d, Textures array = %d, TmapInfo array = %d\n", NumTextures, (int) sizeof(bitmap_index)*NumTextures, (int) sizeof(tmap_info)*NumTextures);
2214 fwrite( &t, sizeof(int), 1, fp );
2215 fwrite( Sounds, sizeof(ubyte), t, fp );
2216 fwrite( AltSounds, sizeof(ubyte), t, fp );
2217 fprintf(tfile,"Num Sounds = %d, Sounds array = %d, AltSounds array = %d\n",t,t,t);
2219 fwrite( &Num_vclips, sizeof(int), 1, fp );
2220 fwrite( Vclip, sizeof(vclip), Num_vclips, fp );
2221 fprintf(tfile, "Num_vclips = %d, Vclip array = %d\n", Num_vclips, (int) sizeof(vclip)*Num_vclips);
2223 fwrite( &Num_effects, sizeof(int), 1, fp );
2224 fwrite( Effects, sizeof(eclip), Num_effects, fp );
2225 fprintf(tfile, "Num_effects = %d, Effects array = %d\n", Num_effects, (int) sizeof(eclip)*Num_effects);
2227 fwrite( &Num_wall_anims, sizeof(int), 1, fp );
2228 fwrite( WallAnims, sizeof(wclip), Num_wall_anims, fp );
2229 fprintf(tfile, "Num_wall_anims = %d, WallAnims array = %d\n", Num_wall_anims, (int) sizeof(wclip)*Num_wall_anims);
2231 t = N_D2_ROBOT_TYPES;
2232 fwrite( &t, sizeof(int), 1, fp );
2233 fwrite( Robot_info, sizeof(robot_info), t, fp );
2234 fprintf(tfile, "N_robot_types = %d, Robot_info array = %d\n", t, (int) sizeof(robot_info)*N_robot_types);
2236 t = N_D2_ROBOT_JOINTS;
2237 fwrite( &t, sizeof(int), 1, fp );
2238 fwrite( Robot_joints, sizeof(jointpos), t, fp );
2239 fprintf(tfile, "N_robot_joints = %d, Robot_joints array = %d\n", t, (int) sizeof(jointpos)*N_robot_joints);
2241 t = N_D2_WEAPON_TYPES;
2242 fwrite( &t, sizeof(int), 1, fp );
2243 fwrite( Weapon_info, sizeof(weapon_info), t, fp );
2244 fprintf(tfile, "N_weapon_types = %d, Weapon_info array = %d\n", N_weapon_types, (int) sizeof(weapon_info)*N_weapon_types);
2246 fwrite( &N_powerup_types, sizeof(int), 1, fp );
2247 fwrite( Powerup_info, sizeof(powerup_type_info), N_powerup_types, fp );
2248 fprintf(tfile, "N_powerup_types = %d, Powerup_info array = %d\n", N_powerup_types, (int) sizeof(powerup_info)*N_powerup_types);
2250 t = N_D2_POLYGON_MODELS;
2251 fwrite( &t, sizeof(int), 1, fp );
2252 fwrite( Polygon_models, sizeof(polymodel), t, fp );
2253 fprintf(tfile, "N_polygon_models = %d, Polygon_models array = %d\n", t, (int) sizeof(polymodel)*t);
2255 for (i=0; i<t; i++ ) {
2256 g3_uninit_polygon_model(Polygon_models[i].model_data); //get RGB colors
2257 fwrite( Polygon_models[i].model_data, sizeof(ubyte), Polygon_models[i].model_data_size, fp );
2258 fprintf(tfile, " Model %d, data size = %d\n", i, Polygon_models[i].model_data_size); s += Polygon_models[i].model_data_size;
2259 g3_init_polygon_model(Polygon_models[i].model_data); //map colors again
2261 fprintf(tfile,"Total model size = %d\n",s);
2263 fwrite( Dying_modelnums, sizeof(int), t, fp );
2264 fwrite( Dead_modelnums, sizeof(int), t, fp );
2265 fprintf(tfile, "Dying_modelnums array = %d, Dead_modelnums array = %d\n", (int) sizeof(int)*t, (int) sizeof(int)*t);
2268 fwrite( &t, sizeof(int), 1, fp );
2269 fwrite( Gauges, sizeof(bitmap_index), t, fp );
2270 fwrite( Gauges_hires, sizeof(bitmap_index), t, fp );
2271 fprintf(tfile, "Num gauge bitmaps = %d, Gauges array = %d, Gauges_hires array = %d\n", t, (int) sizeof(bitmap_index)*t, (int) sizeof(bitmap_index)*t);
2273 t = MAX_OBJ_BITMAPS;
2274 fwrite( &t, sizeof(int), 1, fp );
2275 fwrite( ObjBitmaps, sizeof(bitmap_index), t, fp );
2276 fwrite( ObjBitmapPtrs, sizeof(ushort), t, fp );
2277 fprintf(tfile, "Num obj bitmaps = %d, ObjBitmaps array = %d, ObjBitmapPtrs array = %d\n", t, (int) sizeof(bitmap_index)*t, (int) sizeof(ushort)*t);
2279 fwrite( &only_player_ship, sizeof(player_ship), 1, fp );
2280 fprintf(tfile, "player_ship size = %d\n", (int) sizeof(player_ship));
2282 fwrite( &Num_cockpits, sizeof(int), 1, fp );
2283 fwrite( cockpit_bitmap, sizeof(bitmap_index), Num_cockpits, fp );
2284 fprintf(tfile, "Num_cockpits = %d, cockpit_bitmaps array = %d\n", Num_cockpits, (int) sizeof(bitmap_index)*Num_cockpits);
2286 fwrite( &First_multi_bitmap_num, sizeof(int), 1, fp );
2288 fwrite( &Num_reactors, sizeof(Num_reactors), 1, fp );
2289 fwrite( Reactors, sizeof(*Reactors), Num_reactors, fp);
2290 fprintf(tfile, "Num_reactors = %d, Reactors array = %d\n", Num_reactors, (int) sizeof(*Reactors)*Num_reactors);
2292 fwrite( &Marker_model_num, sizeof(Marker_model_num), 1, fp);
2294 //@@fwrite( &N_controlcen_guns, sizeof(int), 1, fp );
2295 //@@fwrite( controlcen_gun_points, sizeof(vms_vector), N_controlcen_guns, fp );
2296 //@@fwrite( controlcen_gun_dirs, sizeof(vms_vector), N_controlcen_guns, fp );
2299 fwrite( &exit_modelnum, sizeof(int), 1, fp );
2300 fwrite( &destroyed_exit_modelnum, sizeof(int), 1, fp );
2305 bm_write_extra_robots();
2308 void bm_write_extra_robots()
2314 fp = fopen("robots.ham","wb");
2316 t = 0x5848414d; /* 'XHAM' */
2317 fwrite( &t, sizeof(int), 1, fp );
2319 fwrite( &t, sizeof(int), 1, fp );
2322 t = N_weapon_types - N_D2_WEAPON_TYPES;
2323 fwrite( &t, sizeof(int), 1, fp );
2324 fwrite( &Weapon_info[N_D2_WEAPON_TYPES], sizeof(weapon_info), t, fp );
2326 //now write robot info
2328 t = N_robot_types - N_D2_ROBOT_TYPES;
2329 fwrite( &t, sizeof(int), 1, fp );
2330 fwrite( &Robot_info[N_D2_ROBOT_TYPES], sizeof(robot_info), t, fp );
2332 t = N_robot_joints - N_D2_ROBOT_JOINTS;
2333 fwrite( &t, sizeof(int), 1, fp );
2334 fwrite( &Robot_joints[N_D2_ROBOT_JOINTS], sizeof(jointpos), t, fp );
2336 t = N_polygon_models - N_D2_POLYGON_MODELS;
2337 fwrite( &t, sizeof(int), 1, fp );
2338 fwrite( &Polygon_models[N_D2_POLYGON_MODELS], sizeof(polymodel), t, fp );
2340 for (i=N_D2_POLYGON_MODELS; i<N_polygon_models; i++ ) {
2341 g3_uninit_polygon_model(Polygon_models[i].model_data); //get RGB colors
2342 fwrite( Polygon_models[i].model_data, sizeof(ubyte), Polygon_models[i].model_data_size, fp );
2343 g3_init_polygon_model(Polygon_models[i].model_data); //map colors again
2346 fwrite( &Dying_modelnums[N_D2_POLYGON_MODELS], sizeof(int), t, fp );
2347 fwrite( &Dead_modelnums[N_D2_POLYGON_MODELS], sizeof(int), t, fp );
2349 t = N_ObjBitmaps - N_D2_OBJBITMAPS;
2350 fwrite( &t, sizeof(int), 1, fp );
2351 fwrite( &ObjBitmaps[N_D2_OBJBITMAPS], sizeof(bitmap_index), t, fp );
2353 t = N_ObjBitmapPtrs - N_D2_OBJBITMAPPTRS;
2354 fwrite( &t, sizeof(int), 1, fp );
2355 fwrite( &ObjBitmapPtrs[N_D2_OBJBITMAPPTRS], sizeof(ushort), t, fp );
2357 fwrite( ObjBitmapPtrs, sizeof(ushort), t, fp );