Some improvements to scenario-related errors when loading games

- Use the same algorithm for locating scenarios as is used when selecting a scenario to enter
- Improve the error message when the party's scenario is missing - in particular, name the scenario
- Fix legacy saved games in custom scenarios being unloadable
This commit is contained in:
2017-01-30 21:11:08 -05:00
parent e656841b86
commit a37db72920
4 changed files with 56 additions and 45 deletions

View File

@@ -343,44 +343,6 @@ void start_data_dump() {
}
extern fs::path scenDir;
fs::path locate_scenario(std::string scen_name) {
fs::create_directories(scenDir);
std::transform(scen_name.begin(), scen_name.end(), scen_name.begin(), tolower);
size_t dot = scen_name.find_first_of('.');
std::string base_name = scen_name.substr(0,dot);
if(base_name == "valleydy" || base_name == "stealth" || base_name == "zakhazi"/* || base_name == "busywork" */)
return progDir/"Blades of Exile Scenarios"/scen_name;
fs::path scenPath;
for(fs::recursive_directory_iterator iter(scenDir); iter != fs::recursive_directory_iterator(); iter++) {
fs::file_status stat = iter->status();
std::string fname = iter->path().filename().string().c_str();
std::transform(fname.begin(), fname.end(), fname.begin(), tolower);
if(fname == "header.exs") {
if(scen_name != "header.exs") continue;
// We want to support a scenario whose main filename is header.exs, just in case.
// However, any unpacked scenarios would have a header.exs.
// So, skip them if they're in a .boes folder.
fname = iter->path().parent_path().filename().string().c_str();
std::transform(fname.begin(), fname.end(), fname.begin(), tolower);
size_t dot = fname.find_first_of('.');
if(dot != std::string::npos && fname.substr(dot) == ".boes")
continue;
}
if(fname != scen_name) continue;
size_t dot = fname.find_first_of('.');
if(dot == std::string::npos) continue;
if(fname.substr(dot) == ".exs" && stat.type() == fs::regular_file) {
scenPath = iter->path();
break;
}
if(fname.substr(dot) == ".boes" && (stat.type() == fs::regular_file || stat.type() == fs::directory_file)) {
scenPath = iter->path();
break;
}
}
return scenPath;
}
void build_scen_headers() {
fs::create_directories(scenDir);
std::cout << progDir << '\n' << scenDir << std::endl;

View File

@@ -20,6 +20,7 @@ class cUniverse;
namespace fs = boost::filesystem; // TODO: Centralize this alias!
fs::path locate_scenario(std::string scen_name);
bool load_scenario(fs::path file_to_load, cScenario& scenario, bool only_header = false);
bool load_party(fs::path file_to_load, cUniverse& univ);

View File

@@ -222,8 +222,14 @@ bool load_party_v1(fs::path file_to_load, cUniverse& real_univ, bool town_restor
cUniverse univ;
if(in_scen){
fs::path path;
path = progDir/"Blades of Exile Scenarios"/store_party.scen_name;
fs::path path = locate_scenario(store_party.scen_name);
if(path.empty()) {
std::ostringstream msg;
msg << "The scenario that this party was in (\"" << store_party.scen_name;
msg << "\") could not be found. Most likely, it is not installed in the Scenarios directory.";
showError(msg.str());
return false;
}
if(!load_scenario(path, univ.scenario))
return false;
@@ -326,10 +332,14 @@ bool load_party_v2(fs::path file_to_load, cUniverse& real_univ){
}
if(!univ.party.scen_name.empty()) {
fs::path path;
path = scenDir/univ.party.scen_name;
if(!fs::exists(path))
path = progDir/"Blades of Exile Scenarios"/univ.party.scen_name;
fs::path path = locate_scenario(univ.party.scen_name);
if(path.empty()) {
std::ostringstream msg;
msg << "The scenario that this party was in (\"" << univ.party.scen_name;
msg << "\") could not be found. Most likely, it is not installed in the Scenarios directory.";
showError(msg.str());
return false;
}
if(!load_scenario(path, univ.scenario))
return false;

View File

@@ -32,7 +32,7 @@
bool cur_scen_is_mac = true;
extern cCustomGraphics spec_scen_g;
extern fs::path tempDir;
extern fs::path tempDir, scenDir, progDir;
void load_spec_graphics_v1(fs::path scen_file);
void load_spec_graphics_v2(int num_sheets);
@@ -60,6 +60,44 @@ static std::string get_file_error() {
return sout.str();
}
fs::path locate_scenario(std::string scen_name) {
fs::create_directories(scenDir);
std::transform(scen_name.begin(), scen_name.end(), scen_name.begin(), tolower);
size_t dot = scen_name.find_first_of('.');
std::string base_name = scen_name.substr(0,dot);
if(base_name == "valleydy" || base_name == "stealth" || base_name == "zakhazi"/* || base_name == "busywork" */)
return progDir/"Blades of Exile Scenarios"/scen_name;
fs::path scenPath;
for(fs::recursive_directory_iterator iter(scenDir); iter != fs::recursive_directory_iterator(); iter++) {
fs::file_status stat = iter->status();
std::string fname = iter->path().filename().string().c_str();
std::transform(fname.begin(), fname.end(), fname.begin(), tolower);
if(fname == "header.exs") {
if(scen_name != "header.exs") continue;
// We want to support a scenario whose main filename is header.exs, just in case.
// However, any unpacked scenarios would have a header.exs.
// So, skip them if they're in a .boes folder.
fname = iter->path().parent_path().filename().string().c_str();
std::transform(fname.begin(), fname.end(), fname.begin(), tolower);
size_t dot = fname.find_first_of('.');
if(dot != std::string::npos && fname.substr(dot) == ".boes")
continue;
}
if(fname != scen_name) continue;
size_t dot = fname.find_first_of('.');
if(dot == std::string::npos) continue;
if(fname.substr(dot) == ".exs" && stat.type() == fs::regular_file) {
scenPath = iter->path();
break;
}
if(fname.substr(dot) == ".boes" && (stat.type() == fs::regular_file || stat.type() == fs::directory_file)) {
scenPath = iter->path();
break;
}
}
return scenPath;
}
bool load_scenario(fs::path file_to_load, cScenario& scenario, bool only_header) {
// Before loading a scenario, we may need to pop scenario resource paths.
fs::path graphics_path = ResMgr::popPath<ImageRsrc>();