void load_robot_replacements(const d_fname &level_name) { int t,i,j; char ifile_name[FILENAME_LEN]; change_filename_extension(ifile_name, level_name, ".HXM" ); auto fp = PHYSFSX_openReadBuffered(ifile_name); if (!fp) //no robot replacement file return; t = PHYSFSX_readInt(fp); //read id "HXM!" if (t!= 0x21584d48) Error("ID of HXM! file incorrect"); t = PHYSFSX_readInt(fp); //read version if (t<1) Error("HXM! version too old (%d)",t); t = PHYSFSX_readInt(fp); //read number of robots for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read robot number if (i<0 || i>=N_robot_types) Error("Robots number (%d) out of range in (%s). Range = [0..%d].",i,static_cast<const char *>(level_name),N_robot_types-1); robot_info_read(fp, Robot_info[i]); } t = PHYSFSX_readInt(fp); //read number of joints for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read joint number if (i<0 || i>=N_robot_joints) Error("Robots joint (%d) out of range in (%s). Range = [0..%d].",i,static_cast<const char *>(level_name),N_robot_joints-1); jointpos_read(fp, Robot_joints[i]); } t = PHYSFSX_readInt(fp); //read number of polygon models for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read model number if (i<0 || i>=N_polygon_models) Error("Polygon model (%d) out of range in (%s). Range = [0..%d].",i,static_cast<const char *>(level_name),N_polygon_models-1); free_model(Polygon_models[i]); polymodel_read(&Polygon_models[i], fp); polygon_model_data_read(&Polygon_models[i], fp); Dying_modelnums[i] = PHYSFSX_readInt(fp); Dead_modelnums[i] = PHYSFSX_readInt(fp); } t = PHYSFSX_readInt(fp); //read number of objbitmaps for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read objbitmap number if (i < 0 || i >= ObjBitmaps.size()) Error("Object bitmap number (%d) out of range in (%s). Range = [0..%" DXX_PRI_size_type "].", i, static_cast<const char *>(level_name), ObjBitmaps.size() - 1); bitmap_index_read(fp, ObjBitmaps[i]); } t = PHYSFSX_readInt(fp); //read number of objbitmapptrs for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read objbitmapptr number if (i < 0 || i >= ObjBitmapPtrs.size()) Error("Object bitmap pointer (%d) out of range in (%s). Range = [0..%" DXX_PRI_size_type "].", i, static_cast<const char *>(level_name), ObjBitmapPtrs.size() - 1); ObjBitmapPtrs[i] = PHYSFSX_readShort(fp); } Robot_replacements_loaded = 1; }
//loads a level (.LVL) file from disk //returns 0 if success, else error code int load_level(const char * filename_passed) { #ifdef EDITOR int use_compiled_level=1; #endif PHYSFS_file * LoadFile; char filename[PATH_MAX]; int sig, minedata_offset, gamedata_offset, hostagetext_offset; int mine_err, game_err; #ifdef NETWORK int i; #endif #ifdef NETWORK if (Game_mode & GM_NETWORK) { for (i=0;i<MAX_POWERUP_TYPES;i++) { MaxPowerupsAllowed[i]=0; PowerupsInMine[i]=0; } } #endif #ifdef COMPACT_SEGS ncache_flush(); #endif #ifndef RELEASE Level_being_loaded = filename_passed; #endif strcpy(filename,filename_passed); #ifdef EDITOR //if we have the editor, try the LVL first, no matter what was passed. //if we don't have an LVL, try what was passed or SDL/RDL //if we don't have the editor, we just use what was passed change_filename_extension(filename,filename_passed,".lvl"); use_compiled_level = 0; if (!PHYSFSX_exists(filename,1)) { char *p = strrchr(filename_passed, '.'); if (d_stricmp(p, ".lvl")) strcpy(filename, filename_passed); // set to what was passed else change_filename_extension(filename, filename, ".rdl"); use_compiled_level = 1; } #endif if (!PHYSFSX_exists(filename,1)) sprintf(filename,"%s%s",MISSION_DIR,filename_passed); LoadFile = PHYSFSX_openReadBuffered( filename ); if (!LoadFile) { #ifdef EDITOR return 1; #else Error("Can't open file <%s>\n",filename); #endif } strcpy( Gamesave_current_filename, filename ); sig = PHYSFSX_readInt(LoadFile); Gamesave_current_version = PHYSFSX_readInt(LoadFile); minedata_offset = PHYSFSX_readInt(LoadFile); gamedata_offset = PHYSFSX_readInt(LoadFile); Assert(sig == MAKE_SIG('P','L','V','L')); (void)sig; if (Gamesave_current_version < 5) hostagetext_offset = PHYSFSX_readInt(LoadFile); PHYSFSX_fseek(LoadFile,minedata_offset,SEEK_SET); #ifdef EDITOR if (!use_compiled_level) mine_err = load_mine_data(LoadFile); else #endif //NOTE LINK TO ABOVE!! mine_err = load_mine_data_compiled(LoadFile); /* !!!HACK!!! * Descent 1 - Level 19: OBERON MINE has some ugly overlapping rooms (segment 484). * HACK to make this issue less visible by moving one vertex a little. */ if (Current_mission && !d_stricmp("Descent: First Strike",Current_mission_longname) && !d_stricmp("level19.rdl",filename) && PHYSFS_fileLength(LoadFile) == 136706) Vertices[1905].z =-385*F1_0; if (mine_err == -1) { //error!! PHYSFS_close(LoadFile); return 2; } PHYSFSX_fseek(LoadFile,gamedata_offset,SEEK_SET); game_err = load_game_data(LoadFile); if (game_err == -1) { //error!! PHYSFS_close(LoadFile); return 3; } (void)hostagetext_offset; //======================== CLOSE FILE ============================= PHYSFS_close( LoadFile ); #if 0 //def EDITOR #ifndef RELEASE write_game_text_file(filename); if (Errors_in_mine) { if (is_real_level(filename)) { char ErrorMessage[200]; sprintf( ErrorMessage, "Warning: %i errors in %s!\n", Errors_in_mine, Level_being_loaded ); stop_time(); gr_palette_load(gr_palette); nm_messagebox( NULL, 1, "Continue", ErrorMessage ); start_time(); } } #endif #endif #ifdef EDITOR //If an old version, ask the use if he wants to save as new version if (((LEVEL_FILE_VERSION>1) && Gamesave_current_version<LEVEL_FILE_VERSION) || mine_err==1 || game_err==1) { char ErrorMessage[200]; sprintf( ErrorMessage, "You just loaded a old version level. Would\n" "you like to save it as a current version level?"); gr_palette_load(gr_palette); if (nm_messagebox( NULL, 2, "Don't Save", "Save", ErrorMessage )==1) save_level(filename); } #endif #ifdef EDITOR if (EditorWindow) editor_status_fmt("Loaded NEW mine %s, \"%s\"",filename,Current_level_name); #endif #if !defined(NDEBUG) && !defined(COMPACT_SEGS) if (check_segment_connections()) nm_messagebox( "ERROR", 1, "Ok", "Connectivity errors detected in\n" "mine. See monochrome screen for\n" "details, and contact Matt or Mike." ); #endif return 0; }
// ----------------------------------------------------------------------------- // Save game int save_level_sub(char * filename, int compiled_version) { PHYSFS_file * SaveFile; char temp_filename[PATH_MAX]; int minedata_offset=0,gamedata_offset=0,hostagetext_offset=0; // if ( !compiled_version ) { write_game_text_file(filename); if (Errors_in_mine) { if (is_real_level(filename)) { char ErrorMessage[200]; sprintf( ErrorMessage, "Warning: %i errors in this mine!\n", Errors_in_mine ); gr_palette_load(gr_palette); if (nm_messagebox( NULL, 2, "Cancel Save", "Save", ErrorMessage )!=1) { return 1; } } } // change_filename_extension(temp_filename,filename,".LVL"); } // else { change_filename_extension(temp_filename, filename, ".RDL"); } SaveFile = PHYSFSX_openWriteBuffered(temp_filename); if (!SaveFile) { char ErrorMessage[256]; snprintf( ErrorMessage, sizeof(ErrorMessage), "ERROR: Cannot write to '%s'.", temp_filename); gr_palette_load(gr_palette); nm_messagebox( NULL, 1, "Ok", ErrorMessage ); return 1; } if (Current_level_name[0] == 0) strcpy(Current_level_name,"Untitled"); clear_transient_objects(1); //1 means clear proximity bombs compress_objects(); //after this, Highest_object_index == num objects //make sure player is in a segment if (update_object_seg(&Objects[Players[0].objnum]) == 0) { if (ConsoleObject->segnum > Highest_segment_index) ConsoleObject->segnum = 0; compute_segment_center(&ConsoleObject->pos,&(Segments[ConsoleObject->segnum])); } fix_object_segs(); //Write the header PHYSFS_writeSLE32(SaveFile, MAKE_SIG('P','L','V','L')); PHYSFS_writeSLE32(SaveFile, Gamesave_current_version); //save placeholders PHYSFS_writeSLE32(SaveFile, minedata_offset); PHYSFS_writeSLE32(SaveFile, gamedata_offset); PHYSFS_writeSLE32(SaveFile, hostagetext_offset); //Now write the damn data minedata_offset = PHYSFS_tell(SaveFile); #if 0 // only save compiled mine data if ( !compiled_version ) save_mine_data(SaveFile); else #endif save_mine_data_compiled(SaveFile); gamedata_offset = PHYSFS_tell(SaveFile); save_game_data(SaveFile); hostagetext_offset = PHYSFS_tell(SaveFile); PHYSFS_seek(SaveFile, sizeof(int) + sizeof(Gamesave_current_version)); PHYSFS_writeSLE32(SaveFile, minedata_offset); PHYSFS_writeSLE32(SaveFile, gamedata_offset); PHYSFS_writeSLE32(SaveFile, hostagetext_offset); //==================== CLOSE THE FILE ============================= PHYSFS_close(SaveFile); // if ( !compiled_version ) { if (EditorWindow) editor_status_fmt("Saved mine %s, \"%s\"",filename,Current_level_name); } return 0; }
void load_robot_replacements(char *level_name) { PHYSFS_file *fp; int t,i,j; char ifile_name[FILENAME_LEN]; change_filename_extension(ifile_name, level_name, ".HXM" ); fp = PHYSFSX_openReadBuffered(ifile_name); if (!fp) //no robot replacement file return; t = PHYSFSX_readInt(fp); //read id "HXM!" if (t!= 0x21584d48) Error("ID of HXM! file incorrect"); t = PHYSFSX_readInt(fp); //read version if (t<1) Error("HXM! version too old (%d)",t); t = PHYSFSX_readInt(fp); //read number of robots for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read robot number if (i<0 || i>=N_robot_types) Error("Robots number (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_robot_types-1); robot_info_read_n(&Robot_info[i], 1, fp); } t = PHYSFSX_readInt(fp); //read number of joints for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read joint number if (i<0 || i>=N_robot_joints) Error("Robots joint (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_robot_joints-1); jointpos_read_n(&Robot_joints[i], 1, fp); } t = PHYSFSX_readInt(fp); //read number of polygon models for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read model number if (i<0 || i>=N_polygon_models) Error("Polygon model (%d) out of range in (%s). Range = [0..%d].",i,level_name,N_polygon_models-1); free_model(&Polygon_models[i]); polymodel_read(&Polygon_models[i], fp); polygon_model_data_read(&Polygon_models[i], fp); Dying_modelnums[i] = PHYSFSX_readInt(fp); Dead_modelnums[i] = PHYSFSX_readInt(fp); } t = PHYSFSX_readInt(fp); //read number of objbitmaps for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read objbitmap number if (i<0 || i>=MAX_OBJ_BITMAPS) Error("Object bitmap number (%d) out of range in (%s). Range = [0..%d].",i,level_name,MAX_OBJ_BITMAPS-1); bitmap_index_read(&ObjBitmaps[i], fp); } t = PHYSFSX_readInt(fp); //read number of objbitmapptrs for (j=0;j<t;j++) { i = PHYSFSX_readInt(fp); //read objbitmapptr number if (i<0 || i>=MAX_OBJ_BITMAPS) Error("Object bitmap pointer (%d) out of range in (%s). Range = [0..%d].",i,level_name,MAX_OBJ_BITMAPS-1); ObjBitmapPtrs[i] = PHYSFSX_readShort(fp); } PHYSFS_close(fp); Robot_replacements_loaded = 1; }