void ScriptEngine::_AddOpenFile(ScriptDescriptor* sd) { // NOTE: This function assumes that the file is not already open _open_files.insert(std::make_pair(sd->_filename, sd)); // Add the lua_State to the list of opened lua states if it is not already present if (sd->GetAccessMode() == SCRIPT_READ || sd->GetAccessMode() == SCRIPT_MODIFY) { ReadScriptDescriptor* rsd = dynamic_cast<ReadScriptDescriptor*>(sd); if (_open_threads.find(rsd->GetFilename()) == _open_threads.end()) _open_threads[rsd->GetFilename()] = rsd->_lstack; } }
void SkillEditor::_LoadSkills(ReadScriptDescriptor &script, vector<GlobalSkill *> &skills, GLOBAL_SKILL type) { script.OpenTable("skills"); vector<uint32> keys; script.ReadTableKeys(keys); for(uint32 i = 0; i < keys.size(); ++i) skills.push_back(new GlobalSkill(keys[i])); script.CloseAllTables(); script.CloseFile(); } // _LoadSkills(ReadScriptDescriptor, vector<GlobalSkill *>)
bool ScriptEngine::ExecuteLuaFunction(const string& filename, const string& function_name, bool open_tablespace) { ReadScriptDescriptor script; if (script.OpenFile(filename) == false) { return false; } if (script.DoesFunctionExist(function_name) == false) { IF_PRINT_WARNING(SCRIPT_DEBUG) << "failed to find function \"" << function_name << "\" to execute in file: " << filename << endl; script.CloseFile(); return false; } if (open_tablespace == true) { if (script.OpenTablespace() == "") { IF_PRINT_WARNING(SCRIPT_DEBUG) << "failed to open tablespace in file: " << filename << endl; } script.CloseFile(); return false; } bool result = script.ExecuteFunction(function_name); script.CloseFile(); return result; }
void ScriptEngine::DEBUG_DumpScriptsState() { std::cout << "Script files open: " << _open_files.size() << std::endl; std::cout << "-----------------" << std::endl << "Different lua state contents:" << std::endl; for (std::pair<std::string, vt_script::ScriptDescriptor*> openedFile : _open_files) { std::cout << "Script file: " << openedFile.first << " "; if (openedFile.second->GetAccessMode() != SCRIPT_ACCESS_MODE::SCRIPT_READ) { std::cout << "(Write mode)" << std::endl; continue; } std::cout << "(Read mode)" << std::endl; ReadScriptDescriptor* readScript = static_cast<ReadScriptDescriptor*>(openedFile.second); ScriptEngine::DEBUG_PrintLuaStack(readScript->GetLuaState()); } std::cout << "-----------------" << std::endl; std::cout << "Global stack content:" << std::endl; ScriptEngine::DEBUG_PrintLuaStack(_global_state); }
void SkillEditor::_LoadSkills() { string path = string("dat/skills/"); ReadScriptDescriptor script; script.OpenFile(path + "defense.lua", true); script.CloseFile(); script.OpenFile(path + "support.lua", true); script.CloseFile(); vector<GlobalSkill *> skills; if(script.OpenFile(path + "attack.lua", true) != false) _LoadSkills(script, skills, GLOBAL_SKILL_ATTACK); // Now clean up the skills script (due to the way we're storing the scripts in lua, they're all actually in one big table in lua // regardless of the file split on disk vector<GlobalSkill *>::iterator i = skills.begin(); for(; i != skills.end(); ++i) { if((*i)->GetType() == GLOBAL_SKILL_ATTACK) _attack_skills.push_back(*i); else if((*i)->GetType() == GLOBAL_SKILL_DEFEND) _defense_skills.push_back(*i); else if((*i)->GetType() == GLOBAL_SKILL_SUPPORT) _support_skills.push_back(*i); } if(_attack_skills.size() > 0) _current_skill_index[GLOBAL_SKILL_ATTACK] = 0; if(_defense_skills.size() > 0) _current_skill_index[GLOBAL_SKILL_DEFEND] = 0; if(_support_skills.size() > 0) _current_skill_index[GLOBAL_SKILL_SUPPORT] = 0; } // _LoadSkills()
void GlobalWeapon::_LoadWeaponBattleAnimations(ReadScriptDescriptor& script) { //std::map <uint32, std::map<std::string, std::string> > _weapon_animations; _weapon_animations.clear(); // The character id keys std::vector<uint32> char_ids; script.ReadTableKeys("battle_animations", char_ids); if (char_ids.empty()) return; if (!script.OpenTable("battle_animations")) return; for (uint32 i = 0; i < char_ids.size(); ++i) { uint32 char_id = char_ids[i]; // Read all the animation aliases std::vector<std::string> anim_aliases; script.ReadTableKeys(char_id, anim_aliases); if (anim_aliases.empty()) continue; if (!script.OpenTable(char_id)) continue; for (uint32 j = 0; j < anim_aliases.size(); ++j) { std::string anim_alias = anim_aliases[j]; std::string anim_file = script.ReadString(anim_alias); _weapon_animations[char_id].insert(std::make_pair(anim_alias, anim_file)); } script.CloseTable(); // char_id } script.CloseTable(); // battle_animations }
bool TileSupervisor::Load(ReadScriptDescriptor &map_file) { // Load the map dimensions and do some basic sanity checks _num_tile_on_y_axis = map_file.ReadInt("num_tile_rows"); _num_tile_on_x_axis = map_file.ReadInt("num_tile_cols"); // Load all of the tileset images that are used by this map // Contains all of the tileset filenames used (string does not contain path information or file extensions) std::vector<std::string> tileset_filenames; // Temporarily retains all tile images loaded for each tileset. Each inner vector contains 256 StillImage objects std::vector<std::vector<StillImage> > tileset_images; map_file.ReadStringVector("tileset_filenames", tileset_filenames); for(uint32 i = 0; i < tileset_filenames.size(); i++) { std::string tileset_file = tileset_filenames[i]; ReadScriptDescriptor tileset_script; if (!tileset_script.OpenFile(tileset_file)) { PRINT_ERROR << "Couldn't open the tileset definition file: " << tileset_file << std::endl; return false; } if (!tileset_script.OpenTable("tileset")) { PRINT_ERROR << "Couldn't open the 'tileset' table from file: " << tileset_file << std::endl; tileset_script.CloseFile(); return false; } std::string image_filename = tileset_script.ReadString("image"); tileset_script.CloseFile(); tileset_images.push_back(std::vector<StillImage>(TILES_PER_TILESET)); // Each tileset image is 512x512 pixels, yielding 16 * 16 (== 256) 32x32 pixel tiles each if(!ImageDescriptor::LoadMultiImageFromElementGrid(tileset_images[i], image_filename, 16, 16)) { PRINT_ERROR << "failed to load tileset image: " << image_filename << std::endl; return false; } for(uint32 j = 0; j < TILES_PER_TILESET; j++) { tileset_images[i][j].SetDimensions(TILE_LENGTH, TILE_LENGTH); } } if(!map_file.DoesTableExist("layers")) { PRINT_ERROR << "No 'layers' table in the map file." << std::endl; return false; } // Read in the map tile indeces from all tile layers. // The indeces stored for the map layers in this file directly correspond to a location within a tileset. Tilesets contain a total of 256 tiles // each, so 0-255 correspond to the first tileset, 256-511 the second, etc. The tile location within the tileset is also determined by the index, // where the first 16 indeces in the tileset range are the tiles of the first row (left to right), and so on. // Clears out the tiles grid _tile_grid.clear(); std::vector<int32> table_x_indeces; // Used to temporarily store a row of table indeces map_file.OpenTable("layers"); uint32 layers_number = map_file.GetTableSize(); // layers[0]-[n] for(uint32 layer_id = 0; layer_id < layers_number; ++layer_id) { // Opens the sub-table: layers[layer_id] if(!map_file.DoesTableExist(layer_id)) continue; map_file.OpenTable(layer_id); // Add a layer for the base context _tile_grid.resize(layer_id + 1); LAYER_TYPE layer_type = StringToLayerType(map_file.ReadString("type")); if(layer_type == INVALID_LAYER) { PRINT_WARNING << "Ignoring unexisting layer type: " << layer_type << " in file: " << map_file.GetFilename() << std::endl; map_file.CloseTable(); // layers[i] continue; } _tile_grid[layer_id].layer_type = layer_type; // Add the new tile rows (y axis) _tile_grid[layer_id].tiles.resize(_num_tile_on_y_axis); // Read the tile data for(uint32 y = 0; y < _num_tile_on_y_axis; ++y) { table_x_indeces.clear(); // Check to make sure tables are of the proper size if(!map_file.DoesTableExist(y)) { PRINT_ERROR << "the layers[" << layer_id << "] table size was not equal to the number of tile rows specified by the map, " " first missing row: " << y << std::endl; return false; } map_file.ReadIntVector(y, table_x_indeces); // Check the number of columns if(table_x_indeces.size() != _num_tile_on_x_axis) { PRINT_ERROR << "the layers[" << layer_id << "][" << y << "] table size was not equal to the number of tile columns specified by the map, " "should have " << _num_tile_on_x_axis << " values." << std::endl; return false; } // Prepare the columns (x axis) _tile_grid[layer_id].tiles[y].resize(_num_tile_on_x_axis); for(uint32 x = 0; x < _num_tile_on_x_axis; ++x) { _tile_grid[layer_id].tiles[y][x] = table_x_indeces[x]; } } map_file.CloseTable(); // layers[layer_id] } map_file.CloseTable(); // layers // Determine which tiles in each tileset are referenced in this map // Used to determine whether each tile is used by the map or not. An entry of -1 indicates that particular tile is not used std::vector<int16> tile_references; // Set size to be equal to the total number of tiles and initialize all entries to -1 (unreferenced) tile_references.assign(tileset_filenames.size() * TILES_PER_TILESET, -1); // For each layer for(uint32 layer_id = 0; layer_id < layers_number; ++layer_id) { // For each tile id for(uint32 y = 0; y < _num_tile_on_y_axis; ++y) { for(uint32 x = 0; x < _num_tile_on_x_axis; ++x) { if(_tile_grid[layer_id].tiles[y][x] >= 0) tile_references[_tile_grid[layer_id].tiles[y][x] ] = 0; } } } // Translate the tileset tile indeces into indeces for the vector of tile images // Here, we have to convert the original tile indeces defined in the map file into a new form. The original index // indicates the tileset where the tile is used and its location in that tileset. We need to convert those indeces // so that they serve as an index to the MapMode::_tile_images vector, where the tile images will soon be stored. // Keeps track of the next translated index number to assign uint32 next_index = 0; for(uint32 i = 0; i < tile_references.size(); ++i) { if(tile_references[i] >= 0) { tile_references[i] = next_index; next_index++; } } // Now, go back and re-assign all tile layer indeces with the translated indeces // For each layer for(uint32 layer_id = 0; layer_id < layers_number; ++layer_id) { // For each tile id for(uint32 y = 0; y < _num_tile_on_y_axis; ++y) { for(uint32 x = 0; x < _num_tile_on_x_axis; ++x) { if(_tile_grid[layer_id].tiles[y][x] >= 0) _tile_grid[layer_id].tiles[y][x] = tile_references[_tile_grid[layer_id].tiles[y][x] ]; } } } // Parse all of the tileset definition files and create any animated tile images that will be used // Used to access the tileset definition file ReadScriptDescriptor tileset_script; // Temporarily retains the animation data (every two elements corresponds to a pair of tile frame index and display time) std::vector<uint32> animation_info; // Temporarily holds all animated tile images. The map key is the value of the tile index, before reference translation is done in the next step std::map<uint32, AnimatedImage *> tile_animations; for(uint32 i = 0; i < tileset_filenames.size(); i++) { if (!tileset_script.OpenFile(tileset_filenames[i])) { PRINT_ERROR << "map failed to load because it could not open a tileset definition file: " << tileset_filenames[i] << std::endl; return false; } if (!tileset_script.OpenTable("tileset")) { PRINT_ERROR << "map failed to load because it could not open the 'tileset' table from file: " << tileset_filenames[i] << std::endl; tileset_script.CloseFile(); return false; } if(tileset_script.DoesTableExist("animated_tiles")) { tileset_script.OpenTable("animated_tiles"); for(uint32 j = 1; j <= tileset_script.GetTableSize(); j++) { animation_info.clear(); tileset_script.ReadUIntVector(j, animation_info); // The index of the first frame in the animation. (i * TILES_PER_TILESET) factors in which tileset the frame comes from uint32 first_frame_index = animation_info[0] + (i * TILES_PER_TILESET); // If the first tile frame index of this animation was not referenced anywhere in the map, then the animation is unused and // we can safely skip over it and move on to the next one. Otherwise if it is referenced, we have to construct the animated image if(tile_references[first_frame_index] == -1) { continue; } AnimatedImage *new_animation = new AnimatedImage(); new_animation->SetDimensions(TILE_LENGTH, TILE_LENGTH); // Each pair of entries in the animation info indicate the tile frame index (k) and the time (k+1) for(uint32 k = 0; k < animation_info.size(); k += 2) { new_animation->AddFrame(tileset_images[i][animation_info[k]], animation_info[k + 1]); } tile_animations.insert(std::make_pair(first_frame_index, new_animation)); } tileset_script.CloseTable(); } tileset_script.CloseTable(); tileset_script.CloseFile(); } // for (uint32 i = 0; i < tileset_filenames.size(); i++) // Add all referenced tiles to the _tile_images vector, in the proper order for(uint32 i = 0; i < tileset_images.size(); i++) { for(uint32 j = 0; j < TILES_PER_TILESET; j++) { uint32 reference = (i * TILES_PER_TILESET) + j; if(tile_references[reference] >= 0) { // Add the tile as a StillImage if(tile_animations.find(reference) == tile_animations.end()) { _tile_images.push_back(new StillImage(tileset_images[i][j])); } // Add the tile as an AnimatedImage else { _tile_images.push_back(tile_animations[reference]); _animated_tile_images.push_back(tile_animations[reference]); tile_animations.erase(reference); } } } } if(tile_animations.empty() == false) { IF_PRINT_WARNING(MAP_DEBUG) << "one or more tile animations that were created were not added into the map -- this is a memory leak" << std::endl; } // Remove all tileset images. Any tiles which were not added to _tile_images will no longer exist in memory tileset_images.clear(); return true; }
/** \brief Reads in all of the saved game settings and sets values in the according game manager classes *** \return True if the settings were loaded successfully **/ bool LoadSettings() { ReadScriptDescriptor settings; if(!settings.OpenFile(GetSettingsFilename())) return false; if (!settings.OpenTable("settings")) { PRINT_ERROR << "Couldn't open the 'settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } // Load language settings SystemManager->SetLanguage(static_cast<std::string>(settings.ReadString("language"))); if (!settings.OpenTable("key_settings")) { PRINT_ERROR << "Couldn't open the 'key_settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } // Hack to port SDL1.2 arrow values to SDL 2.0 // DEPRECATED: Dump this in a release aka while in Episode II // old - SDL1.2 // settings.key_settings.up = 273 // settings.key_settings.down = 274 // settings.key_settings.left = 276 // settings.key_settings.right = 275 // new - SDL 2.0 // settings.key_settings.up = 1073741906 // settings.key_settings.down = 1073741905 // settings.key_settings.left = 1073741904 // settings.key_settings.right = 1073741903 int32_t key_code = settings.ReadInt("up"); if (key_code == 273) key_code = 1073741906; InputManager->SetUpKey(static_cast<SDL_Keycode>(key_code)); key_code = settings.ReadInt("down"); if (key_code == 274) key_code = 1073741905; InputManager->SetDownKey(static_cast<SDL_Keycode>(key_code)); key_code = settings.ReadInt("left"); if (key_code == 276) key_code = 1073741904; InputManager->SetLeftKey(static_cast<SDL_Keycode>(key_code)); key_code = settings.ReadInt("right"); if (key_code == 275) key_code = 1073741903; InputManager->SetRightKey(static_cast<SDL_Keycode>(key_code)); InputManager->SetConfirmKey(static_cast<SDL_Keycode>(settings.ReadInt("confirm"))); InputManager->SetCancelKey(static_cast<SDL_Keycode>(settings.ReadInt("cancel"))); InputManager->SetMenuKey(static_cast<SDL_Keycode>(settings.ReadInt("menu"))); InputManager->SetMinimapKey(static_cast<SDL_Keycode>(settings.ReadInt("minimap"))); InputManager->SetPauseKey(static_cast<SDL_Keycode>(settings.ReadInt("pause"))); settings.CloseTable(); // key_settings if (!settings.OpenTable("joystick_settings")) { PRINT_ERROR << "Couldn't open the 'joystick_settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } InputManager->SetJoysticksEnabled(!settings.ReadBool("input_disabled")); InputManager->SetJoyIndex(static_cast<int32_t>(settings.ReadInt("index"))); InputManager->SetConfirmJoy(static_cast<uint8_t>(settings.ReadInt("confirm"))); InputManager->SetCancelJoy(static_cast<uint8_t>(settings.ReadInt("cancel"))); InputManager->SetMenuJoy(static_cast<uint8_t>(settings.ReadInt("menu"))); InputManager->SetMinimapJoy(static_cast<uint8_t>(settings.ReadInt("minimap"))); InputManager->SetPauseJoy(static_cast<uint8_t>(settings.ReadInt("pause"))); InputManager->SetQuitJoy(static_cast<uint8_t>(settings.ReadInt("quit"))); // DEPRECATED: Remove the hack in one or two releases... if(settings.DoesIntExist("help")) InputManager->SetHelpJoy(static_cast<uint8_t>(settings.ReadInt("help"))); else InputManager->SetHelpJoy(15); // A high value to avoid getting in the way if(settings.DoesIntExist("x_axis")) InputManager->SetXAxisJoy(static_cast<int8_t>(settings.ReadInt("x_axis"))); if(settings.DoesIntExist("y_axis")) InputManager->SetYAxisJoy(static_cast<int8_t>(settings.ReadInt("y_axis"))); if(settings.DoesIntExist("threshold")) InputManager->SetThresholdJoy(static_cast<uint16_t>(settings.ReadInt("threshold"))); settings.CloseTable(); // joystick_settings if (!settings.OpenTable("video_settings")) { PRINT_ERROR << "Couldn't open the 'video_settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } // Load video settings int32_t resx = settings.ReadInt("screen_resx"); int32_t resy = settings.ReadInt("screen_resy"); VideoManager->SetResolution(resx, resy); VideoManager->SetFullscreen(settings.ReadBool("full_screen")); if (settings.DoesUIntExist("vsync_mode")) VideoManager->SetVSyncMode(settings.ReadUInt("vsync_mode")); if (settings.DoesBoolExist("game_update_mode")) VideoManager->SetGameUpdateMode(settings.ReadBool("game_update_mode")); GUIManager->SetUserMenuSkin(settings.ReadString("ui_theme")); settings.CloseTable(); // video_settings // Load Audio settings if(AUDIO_ENABLE) { if (!settings.OpenTable("audio_settings")) { PRINT_ERROR << "Couldn't open the 'audio_settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } AudioManager->SetMusicVolume(static_cast<float>(settings.ReadFloat("music_vol"))); AudioManager->SetSoundVolume(static_cast<float>(settings.ReadFloat("sound_vol"))); settings.CloseTable(); // audio_settings } // Load Game settings if (!settings.OpenTable("game_options")) { SystemManager->SetMessageSpeed(DEFAULT_MESSAGE_SPEED); } else { if (settings.DoesUIntExist("game_difficulty")) SystemManager->SetGameDifficulty(settings.ReadUInt("game_difficulty")); SystemManager->SetMessageSpeed(settings.ReadFloat("message_speed")); if (settings.DoesBoolExist("battle_target_cursor_memory")) SystemManager->SetBattleTargetMemory(settings.ReadBool("battle_target_cursor_memory")); settings.CloseTable(); // game_options } settings.CloseTable(); // settings if(settings.IsErrorDetected()) { PRINT_ERROR << "Errors while attempting to load the setting file: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } settings.CloseFile(); return true; } // bool LoadSettings()
bool TileSupervisor::Load(ReadScriptDescriptor& map_file) { // Load the map dimensions and do some basic sanity checks _num_tile_on_y_axis = map_file.ReadInt("num_tile_rows"); _num_tile_on_x_axis = map_file.ReadInt("num_tile_cols"); std::vector<int32> context_inherits; //map_file.ReadUIntVector("context_inherits", context_inherits); map_file.OpenTable("contexts"); uint32 num_contexts = map_file.GetTableSize(); for (uint32 context_id = 0; context_id < num_contexts; ++context_id) { map_file.OpenTable(context_id); int32 inheritance = map_file.ReadInt("inherit_from"); // The base context can't inherit from another one if (context_id == 0) inheritance = -1; // A context can't inherit from a context with a higher id, or itself. if ((int32)context_id <= inheritance || inheritance < -1) inheritance = -1; context_inherits.push_back(inheritance); map_file.CloseTable(); } map_file.CloseTable(); // contexts // Load all of the tileset images that are used by this map // Contains all of the tileset filenames used (string does not contain path information or file extensions) std::vector<std::string> tileset_filenames; // Temporarily retains all tile images loaded for each tileset. Each inner vector contains 256 StillImage objects std::vector<std::vector<StillImage> > tileset_images; map_file.ReadStringVector("tileset_filenames", tileset_filenames); for (uint32 i = 0; i < tileset_filenames.size(); i++) { // Construct the image filename from the tileset filename and create a new vector to use in the LoadMultiImage call std::string image_filename = "img/tilesets/" + tileset_filenames[i] + ".png"; tileset_images.push_back(std::vector<StillImage>(TILES_PER_TILESET)); // Each tileset image is 512x512 pixels, yielding 16 * 16 (== 256) 32x32 pixel tiles each if (!ImageDescriptor::LoadMultiImageFromElementGrid(tileset_images[i], image_filename, 16, 16)) { PRINT_ERROR << "failed to load tileset image: " << image_filename << std::endl; return false; } // The map mode coordinate system used corresponds to a tile size of (2.0, 2.0) for (uint32 j = 0; j < TILES_PER_TILESET; j++) { tileset_images[i][j].SetDimensions(2.0f, 2.0f); tileset_images[i][j].Smooth(VideoManager->ShouldSmoothPixelArt()); } } if (!map_file.DoesTableExist("layers")) { PRINT_ERROR << "No 'layers' table in the map file." << std::endl; return false; } // Read in the map tile indeces from all tile layers for the base context // The indeces stored for the map layers in this file directly correspond to a location within a tileset. Tilesets contain a total of 256 tiles // each, so 0-255 correspond to the first tileset, 256-511 the second, etc. The tile location within the tileset is also determined by the index, // where the first 16 indeces in the tileset range are the tiles of the first row (left to right), and so on. // Create the base context _tile_grid.clear(); _tile_grid.insert(std::make_pair(MAP_CONTEXT_01, Context())); std::vector<int32> table_x_indeces; // Used to temporarily store a row of table indeces map_file.OpenTable("layers"); uint32 layers_number = map_file.GetTableSize(); // layers[0]-[n] for (uint32 layer_id = 0; layer_id < layers_number; ++layer_id) { // Opens the sub-table: layers[layer_id] if (!map_file.DoesTableExist(layer_id)) continue; map_file.OpenTable(layer_id); // Add a layer for the base context _tile_grid[MAP_CONTEXT_01].resize(layer_id + 1); LAYER_TYPE layer_type = getLayerType(map_file.ReadString("type")); if (layer_type == INVALID_LAYER) { PRINT_WARNING << "Ignoring unexisting layer type: " << layer_type << " in file: " << map_file.GetFilename() << std::endl; map_file.CloseTable(); // layers[i] continue; } _tile_grid[MAP_CONTEXT_01][layer_id].layer_type = layer_type; // Add the new tile rows (y axis) _tile_grid[MAP_CONTEXT_01][layer_id].tiles.resize(_num_tile_on_y_axis); // Read the tile data for (uint32 y = 0; y < _num_tile_on_y_axis; ++y) { table_x_indeces.clear(); // Check to make sure tables are of the proper size if (!map_file.DoesTableExist(y)) { PRINT_ERROR << "the layers["<< layer_id <<"] table size was not equal to the number of tile rows specified by the map, " " first missing row: " << y << std::endl; return false; } map_file.ReadIntVector(y, table_x_indeces); // Check the number of columns if (table_x_indeces.size() != _num_tile_on_x_axis){ PRINT_ERROR << "the layers[" << layer_id << "]["<< y << "] table size was not equal to the number of tile columns specified by the map, " "should have " << _num_tile_on_x_axis << " values."<< std::endl; return false; } // Prepare the columns (x axis) _tile_grid[MAP_CONTEXT_01][layer_id].tiles[y].resize(_num_tile_on_x_axis); for (uint32 x = 0; x < _num_tile_on_x_axis; ++x) { _tile_grid[MAP_CONTEXT_01][layer_id].tiles[y][x] = table_x_indeces[x]; } } map_file.CloseTable(); // layers[layer_id] } map_file.CloseTable(); // layers // Create each additional context for the map by loading its table data // Load the tile data for each additional map context for (uint32 ctxt = 1; ctxt < num_contexts; ++ctxt) { MAP_CONTEXT this_context = static_cast<MAP_CONTEXT>(1 << ctxt); std::string context_name = "context_"; if (ctxt < 10) // precede single digit context names with a zero context_name += "0"; context_name += NumberToString(ctxt); // Check wether the context inhjeritance id is lower than the current one. if (context_inherits[ctxt] >= (int32)ctxt) { PRINT_WARNING << "Invalid context inheritance found for context id: " << ctxt << ". Permitted values goes from -1 (none) to " << ctxt - 1 << std::endl; continue; } // Initialize this context by making a copy of the base map context first, as most contexts re-use many of the same tiles from the base context // If non-inheriting context, start with empty map! if (context_inherits[ctxt] > -1) { _tile_grid.insert(std::make_pair(this_context, _tile_grid[GetContextMaskFromContextId(context_inherits[ctxt])])); } else { _tile_grid.insert(std::make_pair(this_context, Context())); // Resize the context to have the same size as the base one // The number of layers _tile_grid[this_context].resize(layers_number); // Fro each layer, set up the grid size for (uint32 layer_id = 0; layer_id < layers_number; ++layer_id) { // Type _tile_grid[this_context][layer_id].layer_type = _tile_grid[MAP_CONTEXT_01][layer_id].layer_type; // Height _tile_grid[this_context][layer_id].tiles.resize(_num_tile_on_y_axis); for (uint32 y = 0; y < _num_tile_on_y_axis; ++y) { // and width _tile_grid[this_context][layer_id].tiles[y].assign((size_t)_num_tile_on_x_axis, -1); } } } // Read the table corresponding to this context and modify each tile accordingly. // The context table is an array of integer data. The size of this array should be divisible by four, as every consecutive group of four integers in // this table represent one tile context element. The first integer corresponds to the tile layer (0 = lower, 1 = middle, 2 = upper), the second // and third represent the row and column of the tile respectively, and the fourth value indicates which tile image should be used for this context. // So if the first four entries in the context table were {0, 12, 26, 180}, this would set the lower layer tile at position (12, 26) to the tile // index 180. std::vector<int32> context_data; map_file.ReadIntVector(context_name, context_data); if (context_data.size() % 4 != 0) { PRINT_WARNING << ", context data was not evenly divisible by four (incomplete context data)" << " in context: " << this_context << std::endl; continue; } for (uint32 j = 0; j < context_data.size(); j += 4) { int32 layer_id = context_data[j]; int32 y = context_data[j + 1]; int32 x = context_data[j + 2]; int32 tile_id = context_data[j + 3]; if (y >= _num_tile_on_y_axis || x >= _num_tile_on_x_axis || layer_id >= (int32)_tile_grid[this_context].size()) { PRINT_WARNING << "Invalid context data found for context: " << this_context << ": layer id: " << layer_id << ", x: " << x << ", y: " << y << std::endl; continue; } _tile_grid[this_context][layer_id].tiles[y][x] = tile_id; } } // for (uint32 ctxt = 1; ctxt < map_instance->_num_map_contexts; ++ctxt) // Determine which tiles in each tileset are referenced in this map // Used to determine whether each tile is used by the map or not. An entry of -1 indicates that particular tile is not used std::vector<int16> tile_references; // Set size to be equal to the total number of tiles and initialize all entries to -1 (unreferenced) tile_references.assign(tileset_filenames.size() * TILES_PER_TILESET, -1); std::map<MAP_CONTEXT, Context>::const_iterator it = _tile_grid.begin(); std::map<MAP_CONTEXT, Context>::const_iterator it_end = _tile_grid.end(); // For each context for (; it != it_end; ++it) { // For each layer for (uint32 layer_id = 0; layer_id < layers_number; ++layer_id) { // For each tile id for (uint32 y = 0; y < _num_tile_on_y_axis; ++y) { for (uint32 x = 0; x < _num_tile_on_x_axis; ++x) { if ((it->second)[layer_id].tiles[y][x] >= 0) tile_references[ (it->second)[layer_id].tiles[y][x] ] = 0; } } } } // Translate the tileset tile indeces into indeces for the vector of tile images // Here, we have to convert the original tile indeces defined in the map file into a new form. The original index // indicates the tileset where the tile is used and its location in that tileset. We need to convert those indeces // so that they serve as an index to the MapMode::_tile_images vector, where the tile images will soon be stored. // Keeps track of the next translated index number to assign uint32 next_index = 0; for (uint32 i = 0; i < tile_references.size(); ++i) { if (tile_references[i] >= 0) { tile_references[i] = next_index; next_index++; } } // Now, go back and re-assign all tile layer indeces with the translated indeces std::map<MAP_CONTEXT, Context>::iterator it2 = _tile_grid.begin(); std::map<MAP_CONTEXT, Context>::iterator it2_end = _tile_grid.end(); // For each context for (; it2 != it2_end; ++it2) { // For each layer for (uint32 layer_id = 0; layer_id < layers_number; ++layer_id) { // For each tile id for (uint32 y = 0; y < _num_tile_on_y_axis; ++y) { for (uint32 x = 0; x < _num_tile_on_x_axis; ++x) { if ((it2->second)[layer_id].tiles[y][x] >= 0) (it2->second)[layer_id].tiles[y][x] = tile_references[ (it2->second)[layer_id].tiles[y][x] ]; } } } } // Parse all of the tileset definition files and create any animated tile images that will be used // Used to access the tileset definition file ReadScriptDescriptor tileset_script; // Temporarily retains the animation data (every two elements corresponds to a pair of tile frame index and display time) std::vector<uint32> animation_info; // Temporarily holds all animated tile images. The map key is the value of the tile index, before reference translation is done in the next step std::map<uint32, AnimatedImage*> tile_animations; for (uint32 i = 0; i < tileset_filenames.size(); i++) { if (tileset_script.OpenFile("dat/tilesets/" + tileset_filenames[i] + ".lua") == false) { PRINT_ERROR << "map failed to load because it could not open a tileset definition file: " << tileset_script.GetFilename() << std::endl; exit(1); } tileset_script.OpenTable(tileset_filenames[i]); if (tileset_script.DoesTableExist("animated_tiles") == true) { tileset_script.OpenTable("animated_tiles"); for (uint32 j = 1; j <= tileset_script.GetTableSize(); j++) { animation_info.clear(); tileset_script.ReadUIntVector(j, animation_info); // The index of the first frame in the animation. (i * TILES_PER_TILESET) factors in which tileset the frame comes from uint32 first_frame_index = animation_info[0] + (i * TILES_PER_TILESET); // If the first tile frame index of this animation was not referenced anywhere in the map, then the animation is unused and // we can safely skip over it and move on to the next one. Otherwise if it is referenced, we have to construct the animated image if (tile_references[first_frame_index] == -1) { continue; } AnimatedImage* new_animation = new AnimatedImage(); new_animation->SetDimensions(2.0f, 2.0f); // Each pair of entries in the animation info indicate the tile frame index (k) and the time (k+1) for (uint32 k = 0; k < animation_info.size(); k += 2) { new_animation->AddFrame(tileset_images[i][animation_info[k]], animation_info[k+1]); } tile_animations.insert(std::make_pair(first_frame_index, new_animation)); } tileset_script.CloseTable(); } tileset_script.CloseTable(); tileset_script.CloseFile(); } // for (uint32 i = 0; i < tileset_filenames.size(); i++) // Add all referenced tiles to the _tile_images vector, in the proper order for (uint32 i = 0; i < tileset_images.size(); i++) { for (uint32 j = 0; j < TILES_PER_TILESET; j++) { uint32 reference = (i * TILES_PER_TILESET) + j; if (tile_references[reference] >= 0) { // Add the tile as a StillImage if (tile_animations.find(reference) == tile_animations.end()) { _tile_images.push_back(new StillImage(tileset_images[i][j])); } // Add the tile as an AnimatedImage else { _tile_images.push_back(tile_animations[reference]); _animated_tile_images.push_back(tile_animations[reference]); tile_animations.erase(reference); } } } } if (tile_animations.empty() == false) { IF_PRINT_WARNING(MAP_DEBUG) << "one or more tile animations that were created were not added into the map -- this is a memory leak" << std::endl; } // Remove all tileset images. Any tiles which were not added to _tile_images will no longer exist in memory tileset_images.clear(); return true; } // bool TileSupervisor::Load(ReadScriptDescriptor& map_file)
bool SaveMode::_PreviewGame(const std::string& filename) { // Check for the file existence, prevents a useless warning if(!vt_utils::DoesFileExist(filename)) { _ClearSaveData(false); return false; } ReadScriptDescriptor file; // Clear out the save data namespace to avoid loading false information // when dealing with a save game that has an invalid namespace ScriptManager->DropGlobalTable("save_game1"); if(!file.OpenFile(filename)) { _ClearSaveData(true); return false; } if(!file.DoesTableExist("save_game1")) { file.CloseFile(); _ClearSaveData(true); return false; } // open the namespace that the save game is encapsulated in. file.OpenTable("save_game1"); // The map file, tested after the save game is closed. std::string map_script_filename; std::string map_data_filename; map_script_filename = file.ReadString("map_script_filename"); map_data_filename = file.ReadString("map_data_filename"); // Check whether the map data file is available if (map_data_filename.empty() || !vt_utils::DoesFileExist(map_data_filename)) { file.CloseTable(); // save_game1 file.CloseFile(); _ClearSaveData(true); return false; } // Used to store temp data to populate text boxes int32_t hours = file.ReadInt("play_hours"); int32_t minutes = file.ReadInt("play_minutes"); int32_t seconds = file.ReadInt("play_seconds"); int32_t drunes = file.ReadInt("drunes"); if(!file.DoesTableExist("characters")) { file.CloseTable(); // save_game1 file.CloseFile(); _ClearSaveData(true); return false; } // Read characters table content file.OpenTable("characters"); std::vector<uint32_t> char_ids; file.ReadUIntVector("order", char_ids); // Prereserve characters slots std::vector<GlobalCharacter*> characters; characters.assign(CHARACTERS_SHOWN_SLOTS, nullptr); // Loads only up to the first four slots (Visible battle characters) for(uint32_t i = 0; i < char_ids.size() && i < CHARACTERS_SHOWN_SLOTS; ++i) { // Create a new GlobalCharacter object using the provided id // This loads all of the character's "static" data, such as their name, etc. characters[i] = nullptr; if(!file.DoesTableExist(char_ids[i])) continue; file.OpenTable(char_ids[i]); // Read in all of the character's stats data characters[i] = new GlobalCharacter(char_ids[i], false); characters[i]->SetExperienceLevel(file.ReadUInt("experience_level")); // DEPRECATED: Do not read experience_points anymore in one release uint32_t total_xp = file.ReadUInt("experience_points"); if (total_xp == 0) { total_xp = file.ReadUInt("total_experience_points"); } characters[i]->SetTotalExperiencePoints(total_xp); characters[i]->SetMaxHitPoints(file.ReadUInt("max_hit_points")); characters[i]->SetHitPoints(file.ReadUInt("hit_points")); characters[i]->SetMaxSkillPoints(file.ReadUInt("max_skill_points")); characters[i]->SetSkillPoints(file.ReadUInt("skill_points")); file.CloseTable(); // character id } file.CloseTable(); // characters // Report any errors detected from the previous read operations if(file.IsErrorDetected()) { PRINT_WARNING << "One or more errors occurred while reading the save game file - they are listed below:" << std::endl << file.GetErrorMessages() << std::endl; file.ClearErrors(); } file.CloseTable(); // save_game1 file.CloseFile(); for(uint32_t i = 0; i < CHARACTERS_SHOWN_SLOTS; ++i) { _character_window[i].SetCharacter(characters[i]); } std::ostringstream time_text; time_text << (hours < 10 ? "0" : "") << static_cast<uint32_t>(hours) << ":"; time_text << (minutes < 10 ? "0" : "") << static_cast<uint32_t>(minutes) << ":"; time_text << (seconds < 10 ? "0" : "") << static_cast<uint32_t>(seconds); _time_textbox.SetDisplayText(MakeUnicodeString(time_text.str())); std::ostringstream drunes_amount; drunes_amount << drunes; _drunes_textbox.SetDisplayText(MakeUnicodeString(drunes_amount.str())); // Test the map file // Tests the map file and gets the untranslated map hud name from it. ReadScriptDescriptor map_file; if(!map_file.OpenFile(map_script_filename)) { _ClearSaveData(true); return false; } if (map_file.OpenTablespace().empty()) { _ClearSaveData(true); map_file.CloseFile(); return false; } // Read the in-game location of the save std::string map_hud_name = map_file.ReadString("map_name"); _map_name_textbox.SetDisplayText(UTranslate(map_hud_name)); // Loads the potential location image std::string map_image_filename = map_file.ReadString("map_image_filename"); if (map_image_filename.empty()) { _location_image.Clear(); } else { if (_location_image.Load(map_image_filename)) _location_image.SetWidthKeepRatio(340.0f); } map_file.CloseTable(); // Tablespace map_file.CloseFile(); return true; }
void TileSupervisor::Load(ReadScriptDescriptor& map_file, const MapMode* map_instance) { // TODO: Add some more error checking in this function (such as checking for script errors after reading blocks of data from the map file) // ---------- (1) Load the map dimensions and do some basic sanity checks _num_tile_rows = map_file.ReadInt("num_tile_rows"); _num_tile_cols = map_file.ReadInt("num_tile_cols"); // Check to make sure tables are of the proper size // TODO: we only check that the number of rows are correct, but not the number of columns if (map_file.GetTableSize("lower_layer") != _num_tile_rows) { PRINT_ERROR << "the lower_layer table size was not equal to the number of tile rows specified by the map" << endl; return; } if (map_file.GetTableSize("middle_layer") != _num_tile_rows) { PRINT_ERROR << "the middle_layer table size was not equal to the number of tile rows specified by the map" << endl; return; } if (map_file.GetTableSize("upper_layer") != _num_tile_rows) { PRINT_ERROR << "the upper_layer table size was not equal to the number of tile rows specified by the map" << endl; return; } // ---------- (2) Load all of the tileset images that are used by this map // Contains all of the tileset filenames used (string does not contain path information or file extensions) vector<string> tileset_filenames; // Temporarily retains all tile images loaded for each tileset. Each inner vector contains 256 StillImage objects vector<vector<StillImage> > tileset_images; map_file.ReadStringVector("tileset_filenames", tileset_filenames); for (uint32 i = 0; i < tileset_filenames.size(); i++) { // Construct the image filename from the tileset filename and create a new vector to use in the LoadMultiImage call string image_filename = "img/tilesets/" + tileset_filenames[i] + ".png"; tileset_images.push_back(vector<StillImage>(TILES_PER_TILESET)); // The map mode coordinate system used corresponds to a tile size of (2.0, 2.0) for (uint32 j = 0; j < TILES_PER_TILESET; j++) { tileset_images[i][j].SetDimensions(2.0f, 2.0f); } // Each tileset image is 512x512 pixels, yielding 16 * 16 (== 256) 32x32 pixel tiles each if (ImageDescriptor::LoadMultiImageFromElementGrid(tileset_images[i], image_filename, 16, 16) == false) { PRINT_ERROR << "failed to load tileset image: " << image_filename << endl; exit(1); } } // ---------- (3) Read in the map tile indeces from all three tile layers for the base context // The indeces stored for the map layers in this file directly correspond to a location within a tileset. Tilesets contain a total of 256 tiles // each, so 0-255 correspond to the first tileset, 256-511 the second, etc. The tile location within the tileset is also determined by the index, // where the first 16 indeces in the tileset range are the tiles of the first row (left to right), and so on. // Create and add the 2D tile grid for the base context _tile_grid.clear(); _tile_grid.insert(make_pair(MAP_CONTEXT_01, vector<vector<MapTile> >(_num_tile_rows))); for (uint32 r = 0; r < _num_tile_rows; r++) { _tile_grid[MAP_CONTEXT_01][r].resize(_num_tile_cols); } vector<int32> table_row; // Used to temporarily store a row of table indeces // Read the base context tables for all three layers map_file.OpenTable("lower_layer"); for (uint32 r = 0; r < _num_tile_rows; r++) { table_row.clear(); map_file.ReadIntVector(r, table_row); for (uint32 c = 0; c < _num_tile_cols; c++) { _tile_grid[MAP_CONTEXT_01][r][c].lower_layer = table_row[c]; } } map_file.CloseTable(); map_file.OpenTable("middle_layer"); for (uint32 r = 0; r < _num_tile_rows; r++) { table_row.clear(); map_file.ReadIntVector(r, table_row); for (uint32 c = 0; c < _num_tile_cols; c++) { _tile_grid[MAP_CONTEXT_01][r][c].middle_layer = table_row[c]; } } map_file.CloseTable(); map_file.OpenTable("upper_layer"); for (uint32 r = 0; r < _num_tile_rows; r++) { table_row.clear(); map_file.ReadIntVector(r, table_row); for (uint32 c = 0; c < _num_tile_cols; c++) { _tile_grid[MAP_CONTEXT_01][r][c].upper_layer = table_row[c]; } } map_file.CloseTable(); // ---------- (4) Create each additional context for the map by loading its table data // Load the tile data for each additional map context for (uint32 i = 1; i < map_instance->GetNumMapContexts(); i++) { MAP_CONTEXT this_context = static_cast<MAP_CONTEXT>(1 << i); string context_name = "context_"; if (i < 10) // precede single digit context names with a zero context_name += "0"; context_name += NumberToString(i); // Initialize this context by making a copy of the base map context first, as most contexts re-use many of the same tiles from the base context _tile_grid.insert(make_pair(this_context, _tile_grid[MAP_CONTEXT_01])); // Read the table corresponding to this context and modify each tile accordingly. // The context table is an array of integer data. The size of this array should be divisible by four, as every consecutive group of four integers in // this table represent one tile context element. The first integer corresponds to the tile layer (0 = lower, 1 = middle, 2 = upper), the second // and third represent the row and column of the tile respectively, and the fourth value indicates which tile image should be used for this context. // So if the first four entries in the context table were {0, 12, 26, 180}, this would set the lower layer tile at position (12, 26) to the tile // index 180. vector<int32> context_data; map_file.ReadIntVector(context_name, context_data); if (context_data.size() % 4 != 0) { IF_PRINT_WARNING(MAP_DEBUG) << "for context " << this_context << ", context data was not evenly divisible by four (incomplete context data)" << endl; continue; } for (uint32 j = 0; j < context_data.size(); j += 4) { switch (context_data[j]) { case 0: // lower layer _tile_grid[this_context][context_data[j+1]][context_data[j+2]].lower_layer = context_data[j+3]; break; case 1: // middle layer _tile_grid[this_context][context_data[j+1]][context_data[j+2]].middle_layer = context_data[j+3]; break; case 2: // upper layer _tile_grid[this_context][context_data[j+1]][context_data[j+2]].upper_layer = context_data[j+3]; break; default: IF_PRINT_WARNING(MAP_DEBUG) << "unknown tile layer index reference when loading map context tiles" << endl; break; } } } // for (uint32 i = 1; i < map_instance->_num_map_contexts; i++) // ---------- (5) Determine which tiles in each tileset are referenced in this map // Used to determine whether each tile is used by the map or not. An entry of -1 indicates that particular tile is not used vector<int16> tile_references; // Set size to be equal to the total number of tiles and initialize all entries to -1 (unreferenced) tile_references.assign(tileset_filenames.size() * TILES_PER_TILESET, -1); for (map<MAP_CONTEXT, vector<vector<MapTile> > >::iterator i = _tile_grid.begin(); i != _tile_grid.end(); i++) { for (uint32 r = 0; r < _num_tile_rows; r++) { for (uint32 c = 0; c < _num_tile_cols; c++) { if ((i->second)[r][c].lower_layer >= 0) tile_references[(i->second)[r][c].lower_layer] = 0; if ((i->second)[r][c].middle_layer >= 0) tile_references[(i->second)[r][c].middle_layer] = 0; if ((i->second)[r][c].upper_layer >= 0) tile_references[(i->second)[r][c].upper_layer] = 0; } } } // ---------- (6) Translate the tileset tile indeces into indeces for the vector of tile images // Here, we have to convert the original tile indeces defined in the map file into a new form. The original index // indicates the tileset where the tile is used and its location in that tileset. We need to convert those indeces // so that they serve as an index to the MapMode::_tile_images vector, where the tile images will soon be stored. // Keeps track of the next translated index number to assign uint32 next_index = 0; for (uint32 i = 0; i < tile_references.size(); i++) { if (tile_references[i] >= 0) { tile_references[i] = next_index; next_index++; } } // Now, go back and re-assign all lower, middle, and upper tile layer indeces with the translated indeces for (map<MAP_CONTEXT, vector<vector<MapTile> > >::iterator i = _tile_grid.begin(); i != _tile_grid.end(); i++) { for (uint32 r = 0; r < _num_tile_rows; r++) { for (uint32 c = 0; c < _num_tile_cols; c++) { if ((i->second)[r][c].lower_layer >= 0) (i->second)[r][c].lower_layer = tile_references[(i->second)[r][c].lower_layer]; if ((i->second)[r][c].middle_layer >= 0) (i->second)[r][c].middle_layer = tile_references[(i->second)[r][c].middle_layer]; if ((i->second)[r][c].upper_layer >= 0) (i->second)[r][c].upper_layer = tile_references[(i->second)[r][c].upper_layer]; } } } // ---------- (7) Parse all of the tileset definition files and create any animated tile images that will be used // Used to access the tileset definition file ReadScriptDescriptor tileset_script; // Temporarily retains the animation data (every two elements corresponds to a pair of tile frame index and display time) vector<uint32> animation_info; // Temporarily holds all animated tile images. The map key is the value of the tile index, before reference translation is done in the next step map<uint32, AnimatedImage*> tile_animations; for (uint32 i = 0; i < tileset_filenames.size(); i++) { if (tileset_script.OpenFile("dat/tilesets/" + tileset_filenames[i] + ".lua") == false) { PRINT_ERROR << "map failed to load because it could not open a tileset definition file: " << tileset_script.GetFilename() << endl; exit(1); } tileset_script.OpenTable(tileset_filenames[i]); if (tileset_script.DoesTableExist("animated_tiles") == true) { tileset_script.OpenTable("animated_tiles"); for (uint32 j = 1; j <= tileset_script.GetTableSize(); j++) { animation_info.clear(); tileset_script.ReadUIntVector(j, animation_info); // The index of the first frame in the animation. (i * TILES_PER_TILESET) factors in which tileset the frame comes from uint32 first_frame_index = animation_info[0] + (i * TILES_PER_TILESET); // If the first tile frame index of this animation was not referenced anywhere in the map, then the animation is unused and // we can safely skip over it and move on to the next one. Otherwise if it is referenced, we have to construct the animated image if (tile_references[first_frame_index] == -1) { continue; } AnimatedImage* new_animation = new AnimatedImage(); new_animation->SetDimensions(2.0f, 2.0f); // Each pair of entries in the animation info indicate the tile frame index (k) and the time (k+1) for (uint32 k = 0; k < animation_info.size(); k += 2) { new_animation->AddFrame(tileset_images[i][animation_info[k]], animation_info[k+1]); } tile_animations.insert(make_pair(first_frame_index, new_animation)); } tileset_script.CloseTable(); } tileset_script.CloseTable(); tileset_script.CloseFile(); } // for (uint32 i = 0; i < tileset_filenames.size(); i++) // ---------- (8) Add all referenced tiles to the _tile_images vector, in the proper order for (uint32 i = 0; i < tileset_images.size(); i++) { for (uint32 j = 0; j < TILES_PER_TILESET; j++) { uint32 reference = (i * TILES_PER_TILESET) + j; if (tile_references[reference] >= 0) { // Add the tile as a StillImage if (tile_animations.find(reference) == tile_animations.end()) { _tile_images.push_back(new StillImage(tileset_images[i][j])); } // Add the tile as an AnimatedImage else { _tile_images.push_back(tile_animations[reference]); _animated_tile_images.push_back(tile_animations[reference]); tile_animations.erase(reference); } } } } if (tile_animations.empty() == false) { IF_PRINT_WARNING(MAP_DEBUG) << "one or more tile animations that were created were not added into the map -- this is a memory leak" << endl; } // Remove all tileset images. Any tiles which were not added to _tile_images will no longer exist in memory tileset_images.clear(); } // void TileSupervisor::Load(ReadScriptDescriptor& map_file)
bool SaveMode::_PreviewGame(uint32 id) { std::ostringstream f; f << GetUserDataPath() + "saved_game_" << id << ".lua"; std::string filename = f.str(); // Check for the file existence, prevents a useless warning if(!vt_utils::DoesFileExist(filename)) { _ClearSaveData(false); return false; } ReadScriptDescriptor file; // Clear out the save data namespace to avoid loading false information // when dealing with a save game that has an invalid namespace ScriptManager->DropGlobalTable("save_game1"); if(!file.OpenFile(filename)) { _ClearSaveData(true); return false; } if(!file.DoesTableExist("save_game1")) { file.CloseFile(); _ClearSaveData(true); return false; } // open the namespace that the save game is encapsulated in. file.OpenTable("save_game1"); // The map file, tested after the save game is closed. // DEPRECATED: Old way, will be removed in one release. std::string map_script_filename; std::string map_data_filename; if (file.DoesStringExist("map_filename")) { map_script_filename = file.ReadString("map_filename"); map_data_filename = file.ReadString("map_filename"); } else { map_script_filename = file.ReadString("map_script_filename"); map_data_filename = file.ReadString("map_data_filename"); } // DEPRECATED: Remove in one release // Hack to permit the split of last map data and scripts. if (!map_script_filename.empty() && map_data_filename == map_script_filename) { std::string map_common_name = map_data_filename.substr(0, map_data_filename.length() - 4); map_data_filename = map_common_name + "_map.lua"; map_script_filename = map_common_name + "_script.lua"; } // Used to store temp data to populate text boxes int32 hours = file.ReadInt("play_hours"); int32 minutes = file.ReadInt("play_minutes"); int32 seconds = file.ReadInt("play_seconds"); int32 drunes = file.ReadInt("drunes"); if(!file.DoesTableExist("characters")) { file.CloseTable(); // save_game1 file.CloseFile(); _ClearSaveData(true); return false; } file.OpenTable("characters"); std::vector<uint32> char_ids; file.ReadUIntVector("order", char_ids); GlobalCharacter *character[4]; // Loads only up to the first four slots (Visible battle characters) for(uint32 i = 0; i < 4 && i < char_ids.size(); ++i) { // Create a new GlobalCharacter object using the provided id // This loads all of the character's "static" data, such as their name, etc. character[i] = new GlobalCharacter(char_ids[i], false); if(!file.DoesTableExist(char_ids[i])) continue; file.OpenTable(char_ids[i]); // Read in all of the character's stats data character[i]->SetExperienceLevel(file.ReadUInt("experience_level")); character[i]->SetExperiencePoints(file.ReadUInt("experience_points")); character[i]->SetMaxHitPoints(file.ReadUInt("max_hit_points")); character[i]->SetHitPoints(file.ReadUInt("hit_points")); character[i]->SetMaxSkillPoints(file.ReadUInt("max_skill_points")); character[i]->SetSkillPoints(file.ReadUInt("skill_points")); file.CloseTable(); // character id } file.CloseTable(); // characters // Report any errors detected from the previous read operations if(file.IsErrorDetected()) { PRINT_WARNING << "One or more errors occurred while reading the save game file - they are listed below:" << std::endl << file.GetErrorMessages() << std::endl; file.ClearErrors(); } file.CloseTable(); // save_game1 file.CloseFile(); for(uint32 i = 0; i < 4 && i < char_ids.size(); ++i) { _character_window[i].SetCharacter(character[i]); } std::ostringstream time_text; time_text << (hours < 10 ? "0" : "") << static_cast<uint32>(hours) << ":"; time_text << (minutes < 10 ? "0" : "") << static_cast<uint32>(minutes) << ":"; time_text << (seconds < 10 ? "0" : "") << static_cast<uint32>(seconds); _time_textbox.SetDisplayText(MakeUnicodeString(time_text.str())); std::ostringstream drunes_amount; drunes_amount << drunes; _drunes_textbox.SetDisplayText(MakeUnicodeString(drunes_amount.str())); // Test the map file // Tests the map file and gets the untranslated map hud name from it. ReadScriptDescriptor map_file; if(!map_file.OpenFile(map_script_filename)) { _ClearSaveData(true); return false; } if (map_file.OpenTablespace().empty()) { _ClearSaveData(true); map_file.CloseFile(); return false; } // Read the in-game location of the save std::string map_hud_name = map_file.ReadString("map_name"); _map_name_textbox.SetDisplayText(UTranslate(map_hud_name)); // Loads the potential location image std::string map_image_filename = map_file.ReadString("map_image_filename"); if (map_image_filename.empty()) { _location_image.Clear(); } else { if (_location_image.Load(map_image_filename)) _location_image.SetWidthKeepRatio(340.0f); } map_file.CloseTable(); // Tablespace map_file.CloseFile(); return true; } // bool SaveMode::_PreviewGame(string& filename)
/** \brief Reads in all of the saved game settings and sets values in the according game manager classes *** \return True if the settings were loaded successfully **/ bool LoadSettings() { ReadScriptDescriptor settings; if(!settings.OpenFile(GetSettingsFilename())) return false; if (!settings.OpenTable("settings")) { PRINT_ERROR << "Couldn't open the 'settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } // Load language settings SystemManager->SetLanguage(static_cast<std::string>(settings.ReadString("language"))); if (!settings.OpenTable("key_settings")) { PRINT_ERROR << "Couldn't open the 'key_settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } InputManager->SetUpKey(static_cast<SDLKey>(settings.ReadInt("up"))); InputManager->SetDownKey(static_cast<SDLKey>(settings.ReadInt("down"))); InputManager->SetLeftKey(static_cast<SDLKey>(settings.ReadInt("left"))); InputManager->SetRightKey(static_cast<SDLKey>(settings.ReadInt("right"))); InputManager->SetConfirmKey(static_cast<SDLKey>(settings.ReadInt("confirm"))); InputManager->SetCancelKey(static_cast<SDLKey>(settings.ReadInt("cancel"))); InputManager->SetMenuKey(static_cast<SDLKey>(settings.ReadInt("menu"))); InputManager->SetPauseKey(static_cast<SDLKey>(settings.ReadInt("pause"))); settings.CloseTable(); // key_settings if (!settings.OpenTable("joystick_settings")) { PRINT_ERROR << "Couldn't open the 'joystick_settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } InputManager->SetJoysticksEnabled(!settings.ReadBool("input_disabled")); InputManager->SetJoyIndex(static_cast<int32>(settings.ReadInt("index"))); InputManager->SetConfirmJoy(static_cast<uint8>(settings.ReadInt("confirm"))); InputManager->SetCancelJoy(static_cast<uint8>(settings.ReadInt("cancel"))); InputManager->SetMenuJoy(static_cast<uint8>(settings.ReadInt("menu"))); InputManager->SetPauseJoy(static_cast<uint8>(settings.ReadInt("pause"))); InputManager->SetQuitJoy(static_cast<uint8>(settings.ReadInt("quit"))); if(settings.DoesIntExist("x_axis")) InputManager->SetXAxisJoy(static_cast<int8>(settings.ReadInt("x_axis"))); if(settings.DoesIntExist("y_axis")) InputManager->SetYAxisJoy(static_cast<int8>(settings.ReadInt("y_axis"))); if(settings.DoesIntExist("threshold")) InputManager->SetThresholdJoy(static_cast<uint16>(settings.ReadInt("threshold"))); settings.CloseTable(); // joystick_settings if (!settings.OpenTable("video_settings")) { PRINT_ERROR << "Couldn't open the 'video_settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } // Load video settings int32 resx = settings.ReadInt("screen_resx"); int32 resy = settings.ReadInt("screen_resy"); VideoManager->SetInitialResolution(resx, resy); VideoManager->SetFullscreen(settings.ReadBool("full_screen")); // Enforce smooth tiles graphics at first run if (settings.DoesBoolExist("smooth_graphics")) VideoManager->SetPixelArtSmoothed(settings.ReadBool("smooth_graphics")); else VideoManager->SetPixelArtSmoothed(true); settings.CloseTable(); // video_settings // Load Audio settings if(AUDIO_ENABLE) { if (!settings.OpenTable("audio_settings")) { PRINT_ERROR << "Couldn't open the 'audio_settings' table in: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; settings.CloseFile(); return false; } AudioManager->SetMusicVolume(static_cast<float>(settings.ReadFloat("music_vol"))); AudioManager->SetSoundVolume(static_cast<float>(settings.ReadFloat("sound_vol"))); settings.CloseTable(); // audio_settings } settings.CloseTable(); // settings if(settings.IsErrorDetected()) { PRINT_ERROR << "Errors while attempting to load the setting file: " << settings.GetFilename() << std::endl << settings.GetErrorMessages() << std::endl; return false; } settings.CloseFile(); return true; } // bool LoadSettings()