/* THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. */ /* * * Routines to parse bitmaps.tbl * */ #include #include #include #include #include #include "pstypes.h" #include "gr.h" #include "bm.h" #include "u_mem.h" #include "dxxerror.h" #include "object.h" #include "vclip.h" #include "effects.h" #include "polyobj.h" #include "wall.h" #include "textures.h" #include "game.h" #include "iff.h" #include "hostage.h" #include "powerup.h" #include "laser.h" #include "sounds.h" #include "piggy.h" #include "aistruct.h" #include "robot.h" #include "weapon.h" #include "gauges.h" #include "player.h" #include "fuelcen.h" #include "endlevel.h" #include "cntrlcen.h" #include "args.h" #include "text.h" #include "strutil.h" #ifdef EDITOR #include "editor/texpage.h" #endif #include "compiler-range_for.h" static void bm_read_sound(int skip, int pc_shareware); static void bm_read_robot_ai(int skip); static void bm_read_robot(int skip); static void bm_read_object(int skip); static void bm_read_player_ship(int skip); static void bm_read_some_file(int skip); static void bm_read_weapon(int skip, int unused_flag); static void bm_read_powerup(int unused_flag); static void bm_read_hostage(); static void verify_textures(); #define BM_NONE -1 #define BM_COCKPIT 0 #define BM_TEXTURES 2 #define BM_UNUSED 3 #define BM_VCLIP 4 #define BM_EFFECTS 5 #define BM_ECLIP 6 #define BM_WEAPON 7 #define BM_DEMO 8 #define BM_ROBOTEX 9 #define BM_WALL_ANIMS 12 #define BM_WCLIP 13 #define BM_ROBOT 14 #define BM_GAUGES 20 #define MAX_BITMAPS_PER_BRUSH 30 static short N_ObjBitmaps=0; static short N_ObjBitmapPtrs=0; static int Num_robot_ais = 0; char Powerup_names[MAX_POWERUP_TYPES][POWERUP_NAME_LENGTH]; char Robot_names[MAX_ROBOT_TYPES][ROBOT_NAME_LENGTH]; //---------------- Internal variables --------------------------- static int SuperX = -1; static int Installed=0; static char *arg; static short tmap_count = 0; static short texture_count = 0; static short clip_count = 0; static short clip_num; static short sound_num; static short frames; static float play_time; static int hit_sound = -1; static sbyte bm_flag = BM_NONE; static int abm_flag = 0; static int rod_flag = 0; static short wall_open_sound, wall_close_sound,wall_explodes,wall_blastable, wall_hidden; float vlighting=0; static int obj_eclip; static char *dest_bm; //clip number to play when destroyed static int dest_vclip; //what vclip to play when exploding static int dest_eclip; //what eclip to play when exploding static fix dest_size; //3d size of explosion static int crit_clip; //clip number to play when destroyed static int crit_flag; //flag if this is a destroyed eclip static int tmap1_flag; //flag if this is used as tmap_num (not tmap_num2) static int num_sounds=0; int linenum; //------------------- Useful macros and variables --------------- #define IFTOK(str) if (!strcmp(arg, str)) const char space[3] = " \t"; const char equal_space[4] = " \t="; void remove_char( char * s, char c ) { char *p; p = strchr(s,c); if (p) *p = '\0'; } //--------------------------------------------------------------- int compute_average_pixel(grs_bitmap *n) { int row, column, color; // char *pptr; int total_red, total_green, total_blue; total_red = 0; total_green = 0; total_blue = 0; for (row=0; rowbm_h; row++) for (column=0; columnbm_w; column++) { color = gr_gpixel (n, column, row); total_red += gr_palette[color].r; total_green += gr_palette[color].g; total_blue += gr_palette[color].b; } total_red /= (n->bm_h * n->bm_w); total_green /= (n->bm_h * n->bm_w); total_blue /= (n->bm_h * n->bm_w); return BM_XRGB(total_red/2, total_green/2, total_blue/2); } //--------------------------------------------------------------- // Loads a bitmap from either the piggy file, a r64 file, or a // whatever extension is passed. static bitmap_index bm_load_sub(int skip, char * filename ) { bitmap_index bitmap_num; palette_array_t newpal; int iff_error; //reference parm to avoid warning message char fname[20]; bitmap_num.index = 0; if (skip) { return bitmap_num; } removeext( filename, fname ); bitmap_num=piggy_find_bitmap( fname ); if (bitmap_num.index) { return bitmap_num; } grs_bitmap n; iff_error = iff_read_bitmap(filename,&n,BM_LINEAR,&newpal); if (iff_error != IFF_NO_ERROR) { Error("File %s - IFF error: %s",filename,iff_errormsg(iff_error)); } if ( iff_has_transparency ) gr_remap_bitmap_good( &n, newpal, iff_transparent_color, SuperX ); else gr_remap_bitmap_good( &n, newpal, -1, SuperX ); n.avg_color = compute_average_pixel(&n); bitmap_num = piggy_register_bitmap( &n, fname, 0 ); return bitmap_num; } static void ab_load(int skip, const char * filename, bitmap_index bmp[], unsigned *nframes ) { grs_bitmap * bm[MAX_BITMAPS_PER_BRUSH]; bitmap_index bi; int i; int iff_error; //reference parm to avoid warning message palette_array_t newpal; char fname[20]; char tempname[20]; if (skip) { Assert( bogus_bitmap_initialized != 0 ); bmp[0] = piggy_register_bitmap(&bogus_bitmap, "bogus", 0); *nframes = 1; return; } removeext( filename, fname ); for (i=0; iavg_color = compute_average_pixel(bm[i]); new_bmp = piggy_register_bitmap( bm[i], tempname, 0 ); d_free( bm[i] ); bmp[i] = new_bmp; } } int ds_load(int skip, const char * filename ) { int i; PHYSFS_file * cfp; digi_sound n; char fname[20]; char rawname[100]; if (skip) { // We tell piggy_register_sound it's in the pig file, when in actual fact it's in no file // This just tells piggy_close not to attempt to free it return piggy_register_sound( &bogus_sound, "bogus", 1 ); } removeext(filename, fname); sprintf( rawname, "Sounds/%s.raw", fname ); i=piggy_find_sound( fname ); if (i!=255) { return i; } cfp = PHYSFSX_openReadBuffered(rawname); if (cfp!=NULL) { n.length = PHYSFS_fileLength( cfp ); MALLOC( n.data, ubyte, n.length ); PHYSFS_read( cfp, n.data, 1, n.length ); PHYSFS_close(cfp); n.bits = 8; n.freq = 11025; } else { return 255; } i = piggy_register_sound( &n, fname, 0 ); return i; } //parse a float static float get_float() { char *xarg; xarg = strtok( NULL, space ); return atof( xarg ); } //parse an int static int get_int() { char *xarg; xarg = strtok( NULL, space ); return atoi( xarg ); } // rotates a byte left one bit, preserving the bit falling off the right //void //rotate_left(char *c) //{ // int found; // // found = 0; // if (*c & 0x80) // found = 1; // *c = *c << 1; // if (found) // *c |= 0x01; //} #define LINEBUF_SIZE 600 //----------------------------------------------------------------- // Initializes all properties and bitmaps from BITMAPS.TBL file. int gamedata_read_tbl(int pc_shareware) { PHYSFS_file * InfoFile; char inputline[LINEBUF_SIZE]; int i, have_bin_tbl; ObjType[0] = OL_PLAYER; ObjId[0] = 0; Num_total_object_types = 1; for (i=0; ibm_w!=64)||(bmp->bm_h!=64)||(bmp->bm_rowsize!=64) ) { j++; } } if (j) Error("There are game textures that are not 64x64"); } static void set_lighting_flag(sbyte *bp) { if (vlighting < 0) *bp |= BM_FLAG_NO_LIGHTING; else *bp &= (0xff ^ BM_FLAG_NO_LIGHTING); } static void set_texture_name(char *name) { strcpy ( TmapInfo[texture_count].filename, name ); REMOVE_DOTS(TmapInfo[texture_count].filename); } static void bm_read_eclip(int skip) { bitmap_index bitmap; Assert(clip_num < MAX_EFFECTS); if (clip_num+1 > Num_effects) Num_effects = clip_num+1; Effects[clip_num].flags = 0; if (!abm_flag) { bitmap = bm_load_sub(skip, arg); Effects[clip_num].vc.play_time = fl2f(play_time); Effects[clip_num].vc.num_frames = frames; Effects[clip_num].vc.frame_time = fl2f(play_time)/frames; Assert(clip_count < frames); Effects[clip_num].vc.frames[clip_count] = bitmap; set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags); Assert(!obj_eclip); //obj eclips for non-abm files not supported! Assert(crit_flag==0); if (clip_count == 0) { Effects[clip_num].changing_wall_texture = texture_count; Assert(tmap_count < MAX_TEXTURES); tmap_count++; Textures[texture_count] = bitmap; set_texture_name(arg); Assert(texture_count < MAX_TEXTURES); texture_count++; TmapInfo[texture_count].eclip_num = clip_num; NumTextures = texture_count; } clip_count++; } else { bitmap_index bm[MAX_BITMAPS_PER_BRUSH]; abm_flag = 0; ab_load(skip, arg, bm, &Effects[clip_num].vc.num_frames ); Effects[clip_num].vc.play_time = fl2f(play_time); Effects[clip_num].vc.frame_time = Effects[clip_num].vc.play_time/Effects[clip_num].vc.num_frames; clip_count = 0; set_lighting_flag( &GameBitmaps[bm[clip_count].index].bm_flags); Effects[clip_num].vc.frames[clip_count] = bm[clip_count]; if (!obj_eclip && !crit_flag) { Effects[clip_num].changing_wall_texture = texture_count; Assert(tmap_count < MAX_TEXTURES); tmap_count++; Textures[texture_count] = bm[clip_count]; set_texture_name( arg ); Assert(texture_count < MAX_TEXTURES); TmapInfo[texture_count].eclip_num = clip_num; texture_count++; NumTextures = texture_count; } if (obj_eclip) { if (Effects[clip_num].changing_object_texture == -1) { //first time referenced Effects[clip_num].changing_object_texture = N_ObjBitmaps; // XChange ObjectBitmaps N_ObjBitmaps++; } ObjBitmaps[Effects[clip_num].changing_object_texture] = Effects[clip_num].vc.frames[0]; } //if for an object, Effects_bm_ptrs set in object load for(clip_count=1;clip_count < Effects[clip_num].vc.num_frames; clip_count++) { set_lighting_flag( &GameBitmaps[bm[clip_count].index].bm_flags); Effects[clip_num].vc.frames[clip_count] = bm[clip_count]; } } Effects[clip_num].crit_clip = crit_clip; Effects[clip_num].sound_num = sound_num; if (dest_bm) { //deal with bitmap for blown up clip char short_name[13]; int i; strcpy(short_name,dest_bm); REMOVE_DOTS(short_name); for (i=0;i-1) && (clip_count==0) ) Error( "Wall Clip %d is already used!", clip_num ); WallAnims[clip_num].play_time = fl2f(play_time); WallAnims[clip_num].num_frames = frames; //WallAnims[clip_num].frame_time = fl2f(play_time)/frames; Assert(clip_count < frames); WallAnims[clip_num].frames[clip_count++] = texture_count; WallAnims[clip_num].open_sound = wall_open_sound; WallAnims[clip_num].close_sound = wall_close_sound; Textures[texture_count] = bitmap; set_lighting_flag(&GameBitmaps[bitmap.index].bm_flags); set_texture_name( arg ); Assert(texture_count < MAX_TEXTURES); texture_count++; NumTextures = texture_count; if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1; } else { bitmap_index bm[MAX_BITMAPS_PER_BRUSH]; unsigned nframes; if ( (WallAnims[clip_num].num_frames>-1) ) Error( "AB_Wall clip %d is already used!", clip_num ); abm_flag = 0; ab_load(skip, arg, bm, &nframes ); WallAnims[clip_num].num_frames = nframes; WallAnims[clip_num].play_time = fl2f(play_time); //WallAnims[clip_num].frame_time = fl2f(play_time)/nframes; WallAnims[clip_num].open_sound = wall_open_sound; WallAnims[clip_num].close_sound = wall_close_sound; WallAnims[clip_num].close_sound = wall_close_sound; strcpy(WallAnims[clip_num].filename, arg); REMOVE_DOTS(WallAnims[clip_num].filename); if (clip_num >= Num_wall_anims) Num_wall_anims = clip_num+1; set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); for (clip_count=0;clip_count < WallAnims[clip_num].num_frames; clip_count++) { Textures[texture_count] = bm[clip_count]; set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); WallAnims[clip_num].frames[clip_count] = texture_count; REMOVE_DOTS(arg); sprintf( TmapInfo[texture_count].filename, "%s#%d", arg, clip_count); Assert(texture_count < MAX_TEXTURES); texture_count++; NumTextures = texture_count; } } } static void bm_read_vclip(int skip) { bitmap_index bi; Assert(clip_num < VCLIP_MAXNUM); if (!abm_flag) { if ( (Vclip[clip_num].num_frames>-1) && (clip_count==0) ) Error( "Vclip %d is already used!", clip_num ); bi = bm_load_sub(skip, arg); Vclip[clip_num].play_time = fl2f(play_time); Vclip[clip_num].num_frames = frames; Vclip[clip_num].frame_time = fl2f(play_time)/frames; Vclip[clip_num].light_value = fl2f(vlighting); Vclip[clip_num].sound_num = sound_num; set_lighting_flag(&GameBitmaps[bi.index].bm_flags); Assert(clip_count < frames); Vclip[clip_num].frames[clip_count++] = bi; if (rod_flag) { rod_flag=0; Vclip[clip_num].flags |= VF_ROD; } } else { bitmap_index bm[MAX_BITMAPS_PER_BRUSH]; abm_flag = 0; if ( (Vclip[clip_num].num_frames>-1) ) Error( "AB_Vclip %d is already used!", clip_num ); ab_load(skip, arg, bm, &Vclip[clip_num].num_frames ); if (rod_flag) { //int i; rod_flag=0; Vclip[clip_num].flags |= VF_ROD; } Vclip[clip_num].play_time = fl2f(play_time); Vclip[clip_num].frame_time = fl2f(play_time)/Vclip[clip_num].num_frames; Vclip[clip_num].light_value = fl2f(vlighting); Vclip[clip_num].sound_num = sound_num; set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); for (clip_count=0;clip_count < Vclip[clip_num].num_frames; clip_count++) { set_lighting_flag(&GameBitmaps[bm[clip_count].index].bm_flags); Vclip[clip_num].frames[clip_count] = bm[clip_count]; } } } // ------------------------------------------------------------------------------ static void get4fix(fix *fixp) { char *curtext; int i; for (i=0; i 179) { ff = 179; } ff = ff/360; tt = fl2f(ff); fix_sincos(tt, &temp, &fovp[i]); } } static void clear_to_end_of_line(void) { arg = strtok( NULL, space ); while (arg != NULL) arg = strtok( NULL, space ); } static void bm_read_sound(int skip, int pc_shareware) { int sound_num; int alt_sound_num; sound_num = get_int(); alt_sound_num = pc_shareware ? sound_num : get_int(); if ( sound_num>=MAX_SOUNDS ) Error( "Too many sound files.\n" ); if (sound_num >= num_sounds) num_sounds = sound_num+1; arg = strtok(NULL, space); Sounds[sound_num] = ds_load(skip, arg); if ( alt_sound_num == 0 ) AltSounds[sound_num] = sound_num; else if (alt_sound_num < 0 ) AltSounds[sound_num] = 255; else AltSounds[sound_num] = alt_sound_num; if (Sounds[sound_num] == 255) Error("Can't load soundfile <%s>",arg); } // ------------------------------------------------------------------------------ static void bm_read_robot_ai(int skip) { char *robotnum_text; int robotnum; robot_info *robptr; robotnum_text = strtok(NULL, space); robotnum = atoi(robotnum_text); Assert(robotnum < MAX_ROBOT_TYPES); robptr = &Robot_info[robotnum]; Assert(robotnum == Num_robot_ais); //make sure valid number if (skip) { Num_robot_ais++; clear_to_end_of_line(); return; } Num_robot_ais++; get4fix(robptr->field_of_view); get4fix(robptr->firing_wait); get4byte(robptr->rapidfire_count); get4fix(robptr->turn_time); fix fire_power[NDL]; // damage done by a hit from this robot fix shield[NDL]; // shield strength of this robot get4fix(fire_power); get4fix(shield); get4fix(robptr->max_speed); get4fix(robptr->circle_distance); get4byte(robptr->evade_speed); robptr->always_0xabcd = 0xabcd; adjust_field_of_view(robptr->field_of_view); } // ---------------------------------------------------------------------------------------------- //this will load a bitmap for a polygon models. it puts the bitmap into //the array ObjBitmaps[], and also deals with animating bitmaps //returns a pointer to the bitmap static grs_bitmap *load_polymodel_bitmap(int skip, char *name) { Assert(N_ObjBitmaps < MAX_OBJ_BITMAPS); // Assert( N_ObjBitmaps == N_ObjBitmapPtrs ); if (name[0] == '%') { //an animating bitmap! int eclip_num; eclip_num = atoi(name+1); if (Effects[eclip_num].changing_object_texture == -1) { //first time referenced Effects[eclip_num].changing_object_texture = N_ObjBitmaps; ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps; N_ObjBitmaps++; } else { ObjBitmapPtrs[N_ObjBitmapPtrs++] = Effects[eclip_num].changing_object_texture; } return NULL; } else { ObjBitmaps[N_ObjBitmaps] = bm_load_sub(skip, name); ObjBitmapPtrs[N_ObjBitmapPtrs++] = N_ObjBitmaps; N_ObjBitmaps++; return &GameBitmaps[ObjBitmaps[N_ObjBitmaps-1].index]; } } #define MAX_MODEL_VARIANTS 4 // ------------------------------------------------------------------------------ static void bm_read_robot(int skip) { char *model_name[MAX_MODEL_VARIANTS]; int n_models,i; int first_bitmap_num[MAX_MODEL_VARIANTS]; char *equal_ptr; int exp1_vclip_num=-1; int exp1_sound_num=-1; int exp2_vclip_num=-1; int exp2_sound_num=-1; fix lighting = F1_0/2; // Default fix strength = F1_0*10; // Default strength fix mass = f1_0*4; fix drag = f1_0/2; short weapon_type = 0; int g,s; char name[ROBOT_NAME_LENGTH]; int contains_count=0, contains_id=0, contains_prob=0, contains_type=0; int score_value=1000; int cloak_type=0; // Default = this robot does not cloak int attack_type=0; // Default = this robot attacks by firing (1=lunge) int boss_flag=0; // Default = robot is not a boss. int see_sound = ROBOT_SEE_SOUND_DEFAULT; int attack_sound = ROBOT_ATTACK_SOUND_DEFAULT; int claw_sound = ROBOT_CLAW_SOUND_DEFAULT; Assert(N_robot_types < MAX_ROBOT_TYPES); if (skip) { Robot_info[N_robot_types].model_num = -1; N_robot_types++; Num_total_object_types++; clear_to_end_of_line(); return; } model_name[0] = strtok( NULL, space ); first_bitmap_num[0] = N_ObjBitmapPtrs; n_models = 1; // Process bitmaps bm_flag=BM_ROBOT; arg = strtok( NULL, space ); while (arg!=NULL) { equal_ptr = strchr( arg, '=' ); if ( equal_ptr ) { *equal_ptr='\0'; equal_ptr++; // if we have john=cool, arg is 'john' and equal_ptr is 'cool' if (!d_stricmp( arg, "exp1_vclip" )) { exp1_vclip_num = atoi(equal_ptr); } else if (!d_stricmp( arg, "exp2_vclip" )) { exp2_vclip_num = atoi(equal_ptr); } else if (!d_stricmp( arg, "exp1_sound" )) { exp1_sound_num = atoi(equal_ptr); } else if (!d_stricmp( arg, "exp2_sound" )) { exp2_sound_num = atoi(equal_ptr); } else if (!d_stricmp( arg, "lighting" )) { lighting = fl2f(atof(equal_ptr)); if ( (lighting < 0) || (lighting > F1_0 )) { Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)); } } else if (!d_stricmp( arg, "weapon_type" )) { weapon_type = atoi(equal_ptr); } else if (!d_stricmp( arg, "strength" )) { strength = i2f(atoi(equal_ptr)); } else if (!d_stricmp( arg, "mass" )) { mass = fl2f(atof(equal_ptr)); } else if (!d_stricmp( arg, "drag" )) { drag = fl2f(atof(equal_ptr)); } else if (!d_stricmp( arg, "contains_id" )) { contains_id = atoi(equal_ptr); } else if (!d_stricmp( arg, "contains_type" )) { contains_type = atoi(equal_ptr); } else if (!d_stricmp( arg, "contains_count" )) { contains_count = atoi(equal_ptr); } else if (!d_stricmp( arg, "contains_prob" )) { contains_prob = atoi(equal_ptr); } else if (!d_stricmp( arg, "cloak_type" )) { cloak_type = atoi(equal_ptr); } else if (!d_stricmp( arg, "attack_type" )) { attack_type = atoi(equal_ptr); } else if (!d_stricmp( arg, "boss" )) { boss_flag = atoi(equal_ptr); } else if (!d_stricmp( arg, "score_value" )) { score_value = atoi(equal_ptr); } else if (!d_stricmp( arg, "see_sound" )) { see_sound = atoi(equal_ptr); } else if (!d_stricmp( arg, "attack_sound" )) { attack_sound = atoi(equal_ptr); } else if (!d_stricmp( arg, "claw_sound" )) { claw_sound = atoi(equal_ptr); } else if (!d_stricmp( arg, "name" )) { Assert(strlen(equal_ptr) < ROBOT_NAME_LENGTH); // Oops, name too long. strcpy(name, &equal_ptr[1]); name[strlen(name)-1] = 0; } else if (!d_stricmp( arg, "simple_model" )) { model_name[n_models] = equal_ptr; first_bitmap_num[n_models] = N_ObjBitmapPtrs; n_models++; } } else { // Must be a texture specification... load_polymodel_bitmap(skip, arg); } arg = strtok( NULL, space ); } //clear out anim info for (g=0;g F1_0 )) { Error( "In bitmaps.tbl, lighting value of %.2f is out of range 0..1.\n", f2fl(lighting)); } } else if (!d_stricmp( arg, "strength" )) { strength = fl2f(atof(equal_ptr)); } } else { // Must be a texture specification... load_polymodel_bitmap(skip, arg); } arg = strtok( NULL, space ); } if ( model_name_dead ) n_normal_bitmaps = first_bitmap_num_dead-first_bitmap_num; else n_normal_bitmaps = N_ObjBitmapPtrs-first_bitmap_num; model_num = load_polygon_model(model_name,n_normal_bitmaps,first_bitmap_num,NULL); if (type == OL_CONTROL_CENTER) Reactors[0].n_guns = read_model_guns(model_name,Reactors[0].gun_points,Reactors[0].gun_dirs,NULL); if ( model_name_dead ) Dead_modelnums[model_num] = load_polygon_model(model_name_dead,N_ObjBitmapPtrs-first_bitmap_num_dead,first_bitmap_num_dead,NULL); else Dead_modelnums[model_num] = -1; if (type == -1) Error("No object type specfied for object in BITMAPS.TBL on line %d\n",linenum); ObjType[Num_total_object_types] = type; ObjId[Num_total_object_types] = model_num; ObjStrength[Num_total_object_types] = strength; Num_total_object_types++; if (type == OL_EXIT) { exit_modelnum = model_num; destroyed_exit_modelnum = Dead_modelnums[model_num]; } } void bm_read_player_ship(int skip) { char *model_name_dying=NULL; char *model_name[MAX_MODEL_VARIANTS]; int n_models=0,i; int first_bitmap_num[MAX_MODEL_VARIANTS]; char *equal_ptr; robot_info ri; int last_multi_bitmap_num=-1; // Process bitmaps bm_flag = BM_NONE; arg = strtok( NULL, space ); Player_ship->mass = Player_ship->drag = 0; //stupid defaults Player_ship->expl_vclip_num = -1; while (arg!=NULL) { equal_ptr = strchr( arg, '=' ); if ( equal_ptr ) { *equal_ptr='\0'; equal_ptr++; // if we have john=cool, arg is 'john' and equal_ptr is 'cool' if (!d_stricmp( arg, "model" )) { Assert(n_models==0); model_name[0] = equal_ptr; first_bitmap_num[0] = N_ObjBitmapPtrs; n_models = 1; } else if (!d_stricmp( arg, "simple_model" )) { model_name[n_models] = equal_ptr; first_bitmap_num[n_models] = N_ObjBitmapPtrs; n_models++; if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1) last_multi_bitmap_num=N_ObjBitmapPtrs; } else if (!d_stricmp( arg, "mass" )) Player_ship->mass = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "drag" )) Player_ship->drag = fl2f(atof(equal_ptr)); // else if (!d_stricmp( arg, "low_thrust" )) // Player_ship->low_thrust = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "max_thrust" )) Player_ship->max_thrust = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "reverse_thrust" )) Player_ship->reverse_thrust = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "brakes" )) Player_ship->brakes = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "wiggle" )) Player_ship->wiggle = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "max_rotthrust" )) Player_ship->max_rotthrust = fl2f(atof(equal_ptr)); else if (!d_stricmp( arg, "dying_pof" )) model_name_dying = equal_ptr; else if (!d_stricmp( arg, "expl_vclip_num" )) Player_ship->expl_vclip_num=atoi(equal_ptr); } else if (!d_stricmp( arg, "multi_textures" )) { First_multi_bitmap_num = N_ObjBitmapPtrs; first_bitmap_num[n_models] = N_ObjBitmapPtrs; } else // Must be a texture specification... load_polymodel_bitmap(skip, arg); arg = strtok( NULL, space ); } Assert(model_name != NULL); if (First_multi_bitmap_num!=-1 && last_multi_bitmap_num==-1) last_multi_bitmap_num=N_ObjBitmapPtrs; if (First_multi_bitmap_num==-1) first_bitmap_num[n_models] = N_ObjBitmapPtrs; Assert(last_multi_bitmap_num-First_multi_bitmap_num == (MAX_PLAYERS-1)*2); for (i=0;imodel_num = model_num; else Polygon_models[last_model_num].simpler_model = model_num+1; last_model_num = model_num; } if ( model_name_dying ) { Assert(n_models); 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); } Assert(ri.n_guns == N_PLAYER_GUNS); //calc player gun positions { polymodel *pm; robot_info *r; vms_vector pnt; int mn; //submodel number int gun_num; r = &ri; pm = &Polygon_models[Player_ship->model_num]; for (gun_num=0;gun_numn_guns;gun_num++) { pnt = r->gun_points[gun_num]; mn = r->gun_submodels[gun_num]; //instance up the tree for this gun while (mn != 0) { vm_vec_add2(&pnt,&pm->submodel_offsets[mn]); mn = pm->submodel_parents[mn]; } Player_ship->gun_points[gun_num] = pnt; } } } void bm_read_some_file(int skip) { switch (bm_flag) { case BM_COCKPIT: { bitmap_index bitmap; bitmap = bm_load_sub(skip, arg); Assert( Num_cockpits < N_COCKPIT_BITMAPS ); cockpit_bitmap[Num_cockpits++] = bitmap; //bm_flag = BM_NONE; } break; case BM_GAUGES: bm_read_gauges(skip); break; case BM_WEAPON: bm_read_weapon(skip, 0); break; case BM_VCLIP: bm_read_vclip(skip); break; case BM_ECLIP: bm_read_eclip(skip); break; case BM_TEXTURES: { bitmap_index bitmap; bitmap = bm_load_sub(skip, arg); Assert(tmap_count < MAX_TEXTURES); tmap_count++; Textures[texture_count] = bitmap; set_texture_name( arg ); Assert(texture_count < MAX_TEXTURES); texture_count++; NumTextures = texture_count; } break; case BM_WCLIP: bm_read_wclip(skip); break; default: break; } } // ------------------------------------------------------------------------------ // If unused_flag is set, then this is just a placeholder. Don't actually reference vclips or load bbms. void bm_read_weapon(int skip, int unused_flag) { int i,n; int n_models=0; char *equal_ptr; char *pof_file_inner=NULL; char *model_name[MAX_MODEL_VARIANTS]; int first_bitmap_num[MAX_MODEL_VARIANTS]; int lighted; //flag for whether is a texture is lighted Assert(N_weapon_types < MAX_WEAPON_TYPES); n = N_weapon_types; N_weapon_types++; if (unused_flag) { clear_to_end_of_line(); return; } if (skip) { clear_to_end_of_line(); return; } // Initialize weapon array Weapon_info[n].render_type = WEAPON_RENDER_NONE; // 0=laser, 1=blob, 2=object Weapon_info[n].bitmap.index = 0; Weapon_info[n].model_num = -1; Weapon_info[n].model_num_inner = -1; Weapon_info[n].blob_size = 0x1000; // size of blob Weapon_info[n].flash_vclip = -1; Weapon_info[n].flash_sound = SOUND_LASER_FIRED; Weapon_info[n].flash_size = 0; Weapon_info[n].robot_hit_vclip = -1; Weapon_info[n].robot_hit_sound = -1; Weapon_info[n].wall_hit_vclip = -1; Weapon_info[n].wall_hit_sound = -1; Weapon_info[n].impact_size = 0; for (i=0; ibm_flags |= BM_FLAG_NO_LIGHTING; lighted = 1; //default for next bitmap is lighted } arg = strtok( NULL, space ); } first_bitmap_num[n_models] = N_ObjBitmapPtrs; for (i=0;i