// ----------------------------------------------------------------------------- // Load game // Loads all the relevant data for a level. // If level != -1, it loads the filename with extension changed to .min // Otherwise it loads the appropriate level mine. // returns 0=everything ok, 1=old version, -1=error int LoadMineDataCompiled (CFile& cf, int bFileInfo) { int nStartOffset; nStartOffset = cf.Tell (); InitGameFileInfo (); if (ReadGameFileInfo (cf, nStartOffset)) return -1; if (ReadLevelInfo (cf)) return -1; gameStates.render.bD2XLights = gameStates.app.bD2XLevel && (gameTopFileInfo.fileinfoVersion >= 34); if (bFileInfo) return 0; gameData.objs.nNextSignature = 0; gameData.render.lights.nStatic = 0; nGameSaveOrgRobots = 0; nGameSavePlayers = 0; if (ReadObjectInfo (cf)) return -1; if (ReadWallInfo (cf)) return -1; if (ReadDoorInfo (cf)) return -1; if (ReadTriggerInfo (cf)) return -1; if (ReadReactorInfo (cf)) return -1; if (ReadBotGenInfo (cf)) return -1; if (ReadEquipGenInfo (cf)) return -1; if (ReadLightDeltaIndexInfo (cf)) return -1; if (ReadLightDeltaInfo (cf)) return -1; ClearLightSubtracted (); ResetObjects (gameFileInfo.objects.count); CheckAndLinkObjects (); ClearTransientObjects (1); //1 means clear proximity bombs CheckAndFixDoors (); //gameData.walls.nOpenDoors = gameFileInfo.doors.count; gameData.trigs.m_nTriggers = gameFileInfo.triggers.count; gameData.walls.nWalls = gameFileInfo.walls.count; CheckAndFixWalls (); CheckAndFixTriggers (); gameData.matCens.nBotCenters = gameFileInfo.botGen.count; FixObjectSegs (); #if DBG dump_mine_info (); #endif if ((gameTopFileInfo.fileinfoVersion < GAME_VERSION) && ((gameTopFileInfo.fileinfoVersion != 25) || (GAME_VERSION != 26))) return 1; //means old version return 0; }
// -------------------------------------------------------------------- // Load game // Loads all the relevant data for a level. // If level != -1, it loads the filename with extension changed to .min // Otherwise it loads the appropriate level mine. // returns 0=everything ok, 1=old version, -1=error int load_game_data(PHYSFS_file *LoadFile) { int i,j; short game_top_fileinfo_version; int object_offset; int gs_num_objects; int trig_size; //===================== READ FILE INFO ======================== #if 0 PHYSFS_read(LoadFile, &game_top_fileinfo, sizeof(game_top_fileinfo), 1); #endif // Check signature if (PHYSFSX_readShort(LoadFile) != 0x6705) return -1; // Read and check version number game_top_fileinfo_version = PHYSFSX_readShort(LoadFile); if (game_top_fileinfo_version < GAME_COMPATIBLE_VERSION ) return -1; // We skip some parts of the former game_top_fileinfo PHYSFSX_fseek(LoadFile, 31, SEEK_CUR); object_offset = PHYSFSX_readInt(LoadFile); gs_num_objects = PHYSFSX_readInt(LoadFile); PHYSFSX_fseek(LoadFile, 8, SEEK_CUR); Num_walls = PHYSFSX_readInt(LoadFile); PHYSFSX_fseek(LoadFile, 20, SEEK_CUR); Num_triggers = PHYSFSX_readInt(LoadFile); PHYSFSX_fseek(LoadFile, 24, SEEK_CUR); trig_size = PHYSFSX_readInt(LoadFile); Assert(trig_size == sizeof(ControlCenterTriggers)); (void)trig_size; PHYSFSX_fseek(LoadFile, 4, SEEK_CUR); Num_robot_centers = PHYSFSX_readInt(LoadFile); PHYSFSX_fseek(LoadFile, 4, SEEK_CUR); if (game_top_fileinfo_version >= 31) //load mine filename // read newline-terminated string, not sure what version this changed. PHYSFSX_fgets(Current_level_name,sizeof(Current_level_name),LoadFile); else if (game_top_fileinfo_version >= 14) { //load mine filename // read null-terminated string char *p=Current_level_name; //must do read one char at a time, since no PHYSFSX_fgets() do *p = PHYSFSX_fgetc(LoadFile); while (*p++!=0); } else Current_level_name[0]=0; if (game_top_fileinfo_version >= 19) { //load pof names N_save_pof_names = PHYSFSX_readShort(LoadFile); if (N_save_pof_names != 0x614d && N_save_pof_names != 0x5547) { // "Ma"de w/DMB beta/"GU"ILE Assert(N_save_pof_names < MAX_POLYGON_MODELS); PHYSFS_read(LoadFile,Save_pof_names,N_save_pof_names,FILENAME_LEN); } } //===================== READ PLAYER INFO ========================== //===================== READ OBJECT INFO ========================== Gamesave_num_org_robots = 0; Gamesave_num_players = 0; if (object_offset > -1) { if (PHYSFSX_fseek( LoadFile, object_offset, SEEK_SET )) Error( "Error seeking to object_offset in gamesave.c" ); for (i = 0; i < gs_num_objects; i++) { read_object(&Objects[i], LoadFile, game_top_fileinfo_version); Objects[i].signature = obj_get_signature(); verify_object( &Objects[i] ); } } //===================== READ WALL INFO ============================ for (i = 0; i < Num_walls; i++) { if (game_top_fileinfo_version >= 20) wall_read(&Walls[i], LoadFile); // v20 walls and up. else if (game_top_fileinfo_version >= 17) { v19_wall w; v19_wall_read(&w, LoadFile); Walls[i].segnum = w.segnum; Walls[i].sidenum = w.sidenum; Walls[i].linked_wall = w.linked_wall; Walls[i].type = w.type; Walls[i].flags = w.flags; Walls[i].hps = w.hps; Walls[i].trigger = w.trigger; Walls[i].clip_num = convert_wclip(w.clip_num); Walls[i].keys = w.keys; Walls[i].state = WALL_DOOR_CLOSED; } else { v16_wall w; v16_wall_read(&w, LoadFile); Walls[i].segnum = Walls[i].sidenum = Walls[i].linked_wall = -1; Walls[i].type = w.type; Walls[i].flags = w.flags; Walls[i].hps = w.hps; Walls[i].trigger = w.trigger; Walls[i].clip_num = convert_wclip(w.clip_num); Walls[i].keys = w.keys; } } #if 0 //===================== READ DOOR INFO ============================ if (game_fileinfo.doors_offset > -1) { if (!PHYSFSX_fseek( LoadFile, game_fileinfo.doors_offset,SEEK_SET )) { for (i=0;i<game_fileinfo.doors_howmany;i++) { if (game_top_fileinfo_version >= 20) active_door_read(&ActiveDoors[i], LoadFile); // version 20 and up else { v19_door d; int p; v19_door_read(&d, LoadFile); ActiveDoors[i].n_parts = d.n_parts; for (p=0;p<d.n_parts;p++) { int cseg,cside; cseg = Segments[d.seg[p]].children[d.side[p]]; cside = find_connect_side(&Segments[d.seg[p]],&Segments[cseg]); ActiveDoors[i].front_wallnum[p] = Segments[d.seg[p]].sides[d.side[p]].wall_num; ActiveDoors[i].back_wallnum[p] = Segments[cseg].sides[cside].wall_num; } } } } } #endif // 0 //==================== READ TRIGGER INFO ========================== for (i = 0; i < Num_triggers; i++) { if (game_top_fileinfo_version <= 25) trigger_read(&Triggers[i], LoadFile); else { int type; switch ((type = PHYSFSX_readByte(LoadFile))) { case 0: // door Triggers[i].type = 0; Triggers[i].flags = TRIGGER_CONTROL_DOORS; break; case 2: // matcen Triggers[i].type = 0; Triggers[i].flags = TRIGGER_MATCEN; break; case 3: // exit Triggers[i].type = 0; Triggers[i].flags = TRIGGER_EXIT; break; case 4: // secret exit Triggers[i].type = 0; Triggers[i].flags = TRIGGER_SECRET_EXIT; break; case 5: // illusion off Triggers[i].type = 0; Triggers[i].flags = TRIGGER_ILLUSION_OFF; break; case 6: // illusion on Triggers[i].type = 0; Triggers[i].flags = TRIGGER_ILLUSION_ON; break; default: con_printf(CON_URGENT,"Warning: unsupported trigger type %d (%d)\n", type, i); } if (PHYSFSX_readByte(LoadFile) & 2) // one shot Triggers[i].flags |= TRIGGER_ONE_SHOT; Triggers[i].num_links = PHYSFSX_readShort(LoadFile); Triggers[i].value = PHYSFSX_readInt(LoadFile); Triggers[i].time = PHYSFSX_readInt(LoadFile); for (j=0; j<MAX_WALLS_PER_LINK; j++ ) Triggers[i].seg[j] = PHYSFSX_readShort(LoadFile); for (j=0; j<MAX_WALLS_PER_LINK; j++ ) Triggers[i].side[j] = PHYSFSX_readShort(LoadFile); } } //================ READ CONTROL CENTER TRIGGER INFO =============== control_center_triggers_read_n(&ControlCenterTriggers, 1, LoadFile); //================ READ MATERIALOGRIFIZATIONATORS INFO =============== for (i = 0; i < Num_robot_centers; i++) { matcen_info_read(&RobotCenters[i], LoadFile, game_top_fileinfo_version); // Set links in RobotCenters to Station array for (j = 0; j <= Highest_segment_index; j++) if (Segments[j].special == SEGMENT_IS_ROBOTMAKER) if (Segments[j].matcen_num == i) RobotCenters[i].fuelcen_num = Segments[j].value; } //========================= UPDATE VARIABLES ====================== reset_objects(gs_num_objects); for (i=0; i<MAX_OBJECTS; i++) { Objects[i].next = Objects[i].prev = -1; if (Objects[i].type != OBJ_NONE) { int objsegnum = Objects[i].segnum; if (objsegnum > Highest_segment_index) //bogus object Objects[i].type = OBJ_NONE; else { Objects[i].segnum = -1; //avoid Assert() obj_link(i,objsegnum); } } } clear_transient_objects(1); //1 means clear proximity bombs // Make sure non-transparent doors are set correctly. for (i=0; i< Num_segments; i++) for (j=0;j<MAX_SIDES_PER_SEGMENT;j++) { side *sidep = &Segments[i].sides[j]; if ((sidep->wall_num != -1) && (Walls[sidep->wall_num].clip_num != -1)) { if (WallAnims[Walls[sidep->wall_num].clip_num].flags & WCF_TMAP1) { sidep->tmap_num = WallAnims[Walls[sidep->wall_num].clip_num].frames[0]; sidep->tmap_num2 = 0; } } } reset_walls(); #if 0 Num_open_doors = game_fileinfo.doors_howmany; #endif // 0 Num_open_doors = 0; //go through all walls, killing references to invalid triggers for (i=0;i<Num_walls;i++) if (Walls[i].trigger >= Num_triggers) { Walls[i].trigger = -1; //kill trigger } //go through all triggers, killing unused ones for (i=0;i<Num_triggers;) { int w; // Find which wall this trigger is connected to. for (w=0; w<Num_walls; w++) if (Walls[w].trigger == i) break; #ifdef EDITOR if (w == Num_walls) { remove_trigger_num(i); } else #endif i++; } // MK, 10/17/95: Make walls point back at the triggers that control them. // Go through all triggers, stuffing controlling_trigger field in Walls. { int t; for (t=0; t<Num_triggers; t++) { int l; for (l=0; l<Triggers[t].num_links; l++) { int seg_num; seg_num = Triggers[t].seg[l]; //check to see that if a trigger requires a wall that it has one, //and if it requires a matcen that it has one if (Triggers[t].type == TRIGGER_MATCEN) { if (Segments[seg_num].special != SEGMENT_IS_ROBOTMAKER) Int3(); //matcen trigger doesn't point to matcen } } } } //fix old wall structs if (game_top_fileinfo_version < 17) { int segnum,sidenum,wallnum; for (segnum=0; segnum<=Highest_segment_index; segnum++) for (sidenum=0;sidenum<6;sidenum++) if ((wallnum=Segments[segnum].sides[sidenum].wall_num) != -1) { Walls[wallnum].segnum = segnum; Walls[wallnum].sidenum = sidenum; } } #ifndef NDEBUG { int sidenum; for (sidenum=0; sidenum<6; sidenum++) { int wallnum = Segments[Highest_segment_index].sides[sidenum].wall_num; if (wallnum != -1) if ((Walls[wallnum].segnum != Highest_segment_index) || (Walls[wallnum].sidenum != sidenum)) Int3(); // Error. Bogus walls in this segment. // Consult Yuan or Mike. } } #endif //create_local_segment_data(); fix_object_segs(); #ifndef NDEBUG dump_mine_info(); #endif if (game_top_fileinfo_version < GAME_VERSION) return 1; //means old version else return 0; }