Fixed a bunch of issues with game loading
* If no game was show in the dialog (due to an invalid filter) one could still use Enter to load a game * In the same situation above, ESC would cause a crash * Canceling the Select Difficulty dialog would still try to load a game This might have been the intended behavior, but it's not optimal.
This commit is contained in:
parent
9ea794e5a4
commit
a0ad80299b
4 changed files with 123 additions and 160 deletions
|
@ -41,7 +41,6 @@
|
|||
#include "gui/widgets/window.hpp"
|
||||
#include "image.hpp"
|
||||
#include "language.hpp"
|
||||
#include "savegame.hpp"
|
||||
#include "serialization/string_utils.hpp"
|
||||
|
||||
#include <cctype>
|
||||
|
@ -89,30 +88,23 @@ namespace gui2
|
|||
|
||||
REGISTER_DIALOG(game_load)
|
||||
|
||||
tgame_load::tgame_load(const config& cache_config)
|
||||
: txtFilter_(register_text("txtFilter", true))
|
||||
, chk_change_difficulty_(register_bool("change_difficulty", true))
|
||||
, chk_show_replay_(register_bool("show_replay", true))
|
||||
, chk_cancel_orders_(register_bool("cancel_orders", true))
|
||||
, filename_()
|
||||
, change_difficulty_(false)
|
||||
, show_replay_(false)
|
||||
, cancel_orders_(false)
|
||||
tgame_load::tgame_load(const config& cache_config, savegame::load_game_metadata& data)
|
||||
: filename_(data.filename)
|
||||
, change_difficulty_(register_bool("change_difficulty", true, data.select_difficulty))
|
||||
, show_replay_(register_bool("show_replay", true, data.show_replay))
|
||||
, cancel_orders_(register_bool("cancel_orders", true, data.cancel_orders))
|
||||
, summary_(data.summary)
|
||||
, games_({savegame::get_saves_list()})
|
||||
, cache_config_(cache_config)
|
||||
, last_words_()
|
||||
, summary_()
|
||||
{
|
||||
}
|
||||
|
||||
void tgame_load::pre_show(twindow& window)
|
||||
{
|
||||
assert(txtFilter_);
|
||||
|
||||
find_widget<tminimap>(&window, "minimap", false).set_config(&cache_config_);
|
||||
|
||||
ttext_box* filter
|
||||
= find_widget<ttext_box>(&window, "txtFilter", false, true);
|
||||
ttext_box* filter = find_widget<ttext_box>(&window, "txtFilter", false, true);
|
||||
|
||||
filter->set_text_changed_callback(
|
||||
std::bind(&tgame_load::filter_text_changed, this, _1, _2));
|
||||
|
@ -169,20 +161,19 @@ void tgame_load::display_savegame(twindow& window)
|
|||
|
||||
savegame::save_info& game = games_[selected_row];
|
||||
filename_ = game.name();
|
||||
|
||||
const config& summary = game.summary();
|
||||
summary_ = game.summary();
|
||||
|
||||
find_widget<tminimap>(&window, "minimap", false)
|
||||
.set_map_data(summary["map_data"]);
|
||||
.set_map_data(summary_["map_data"]);
|
||||
|
||||
find_widget<tlabel>(&window, "lblScenario", false)
|
||||
.set_label(summary["label"]);
|
||||
.set_label(summary_["label"]);
|
||||
|
||||
tlistbox& leader_list = find_widget<tlistbox>(&window, "leader_list", false);
|
||||
|
||||
leader_list.clear();
|
||||
|
||||
for(const auto& leader : summary.child_range("leader")) {
|
||||
for(const auto& leader : summary_.child_range("leader")) {
|
||||
std::map<std::string, string_map> data;
|
||||
string_map item;
|
||||
|
||||
|
@ -209,21 +200,16 @@ void tgame_load::display_savegame(twindow& window)
|
|||
|
||||
std::stringstream str;
|
||||
str << game.format_time_local() << "\n";
|
||||
evaluate_summary_string(str, summary);
|
||||
evaluate_summary_string(str, summary_);
|
||||
|
||||
find_widget<tlabel>(&window, "lblSummary", false).set_label(str.str());
|
||||
|
||||
ttoggle_button& replay_toggle =
|
||||
find_widget<ttoggle_button>(&window, "show_replay", false);
|
||||
ttoggle_button& replay_toggle = dynamic_cast<ttoggle_button&>(*show_replay_->widget());
|
||||
ttoggle_button& cancel_orders_toggle = dynamic_cast<ttoggle_button&>(*cancel_orders_->widget());
|
||||
ttoggle_button& change_difficulty_toggle = dynamic_cast<ttoggle_button&>(*change_difficulty_->widget());
|
||||
|
||||
ttoggle_button& cancel_orders_toggle =
|
||||
find_widget<ttoggle_button>(&window, "cancel_orders", false);
|
||||
|
||||
ttoggle_button& change_difficulty_toggle =
|
||||
find_widget<ttoggle_button>(&window, "change_difficulty", false);
|
||||
|
||||
const bool is_replay = savegame::loadgame::is_replay_save(summary);
|
||||
const bool is_scenario_start = summary["turn"].empty();
|
||||
const bool is_replay = savegame::loadgame::is_replay_save(summary_);
|
||||
const bool is_scenario_start = summary_["turn"].empty();
|
||||
|
||||
// Always toggle show_replay on if the save is a replay
|
||||
replay_toggle.set_value(is_replay);
|
||||
|
@ -278,19 +264,14 @@ void tgame_load::filter_text_changed(ttext_* textbox, const std::string& text)
|
|||
}
|
||||
|
||||
list.set_row_shown(show_items);
|
||||
}
|
||||
|
||||
void tgame_load::post_show(twindow& window)
|
||||
{
|
||||
change_difficulty_ = chk_change_difficulty_->get_widget_value(window);
|
||||
show_replay_ = chk_show_replay_->get_widget_value(window);
|
||||
cancel_orders_ = chk_cancel_orders_->get_widget_value(window);
|
||||
const bool any_shown = list.any_rows_shown();
|
||||
|
||||
if(!games_.empty()) {
|
||||
const int index =
|
||||
find_widget<tlistbox>(&window, "savegame_list", false).get_selected_row();
|
||||
summary_ = games_[index].summary();
|
||||
}
|
||||
// Disable Load button if no games are available
|
||||
find_widget<tbutton>(&window, "ok", false).set_active(any_shown);
|
||||
|
||||
// Diable 'Enter' loading if no games are available
|
||||
window.set_enter_disabled(!any_shown);
|
||||
}
|
||||
|
||||
void tgame_load::evaluate_summary_string(std::stringstream& str,
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
#define GUI_DIALOGS_LOAD_GAME_HPP_INCLUDED
|
||||
|
||||
#include "gui/dialogs/dialog.hpp"
|
||||
#include "gui/dialogs/transient_message.hpp"
|
||||
#include "savegame.hpp"
|
||||
#include "save_index.hpp"
|
||||
#include "tstring.hpp"
|
||||
|
||||
|
@ -28,37 +30,22 @@ class ttext_;
|
|||
class tgame_load : public tdialog
|
||||
{
|
||||
public:
|
||||
explicit tgame_load(const config& cache_config);
|
||||
tgame_load(const config& cache_config, savegame::load_game_metadata& data);
|
||||
|
||||
const std::string& filename() const
|
||||
static bool execute(const config& cache_config, savegame::load_game_metadata& data, CVideo& video)
|
||||
{
|
||||
return filename_;
|
||||
}
|
||||
bool change_difficulty() const
|
||||
{
|
||||
return change_difficulty_;
|
||||
}
|
||||
bool show_replay() const
|
||||
{
|
||||
return show_replay_;
|
||||
}
|
||||
bool cancel_orders() const
|
||||
{
|
||||
return cancel_orders_;
|
||||
}
|
||||
const config& summary()
|
||||
{
|
||||
return summary_;
|
||||
if(savegame::get_saves_list().empty()) {
|
||||
gui2::show_transient_message(video, _("No Saved Games"), _("There are no save files to load"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return tgame_load(cache_config, data).show(video);
|
||||
}
|
||||
|
||||
protected:
|
||||
private:
|
||||
/** Inherited from tdialog. */
|
||||
void pre_show(twindow& window);
|
||||
|
||||
/** Inherited from tdialog. */
|
||||
void post_show(twindow& window);
|
||||
|
||||
private:
|
||||
/** Inherited from tdialog, implemented by REGISTER_DIALOG. */
|
||||
virtual const std::string& window_id() const;
|
||||
|
||||
|
@ -66,25 +53,20 @@ private:
|
|||
void delete_button_callback(twindow& window);
|
||||
|
||||
void display_savegame(twindow& window);
|
||||
void evaluate_summary_string(std::stringstream& str,
|
||||
const config& cfg_summary);
|
||||
void evaluate_summary_string(std::stringstream& str, const config& cfg_summary);
|
||||
|
||||
tfield_text* txtFilter_;
|
||||
tfield_bool* chk_change_difficulty_;
|
||||
tfield_bool* chk_show_replay_;
|
||||
tfield_bool* chk_cancel_orders_;
|
||||
std::string& filename_;
|
||||
|
||||
std::string filename_;
|
||||
bool change_difficulty_;
|
||||
bool show_replay_;
|
||||
bool cancel_orders_;
|
||||
tfield_bool* change_difficulty_;
|
||||
tfield_bool* show_replay_;
|
||||
tfield_bool* cancel_orders_;
|
||||
|
||||
config& summary_;
|
||||
|
||||
std::vector<savegame::save_info> games_;
|
||||
const config& cache_config_;
|
||||
|
||||
std::vector<std::string> last_words_;
|
||||
|
||||
config summary_;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
122
src/savegame.cpp
122
src/savegame.cpp
|
@ -85,46 +85,16 @@ loadgame::loadgame(CVideo& video, const config& game_config, saved_game& gamesta
|
|||
: game_config_(game_config)
|
||||
, video_(video)
|
||||
, gamestate_(gamestate)
|
||||
, filename_()
|
||||
, difficulty_()
|
||||
, load_config_()
|
||||
, show_replay_(false)
|
||||
, cancel_orders_(false)
|
||||
, select_difficulty_(false)
|
||||
, summary_()
|
||||
, load_data_()
|
||||
{}
|
||||
|
||||
void loadgame::show_dialog()
|
||||
bool loadgame::show_difficulty_dialog()
|
||||
{
|
||||
if(get_saves_list().empty()) {
|
||||
gui2::show_transient_message(video_, _("No Saved Games"),
|
||||
_("There are no save files to load"));
|
||||
return;
|
||||
if(load_data_.summary["corrupt"].to_bool()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: Integrate the load_game dialog into this class
|
||||
// something to watch for the curious, but not yet ready to go
|
||||
gui2::tgame_load load_dialog(game_config_);
|
||||
load_dialog.show(video_);
|
||||
|
||||
if (load_dialog.get_retval() == gui2::twindow::OK) {
|
||||
select_difficulty_ = load_dialog.change_difficulty();
|
||||
|
||||
filename_ = load_dialog.filename();
|
||||
show_replay_ = load_dialog.show_replay();
|
||||
cancel_orders_ = load_dialog.cancel_orders();
|
||||
|
||||
summary_ = load_dialog.summary();
|
||||
}
|
||||
}
|
||||
|
||||
void loadgame::show_difficulty_dialog()
|
||||
{
|
||||
if(summary_["corrupt"].to_bool()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string campaign_id = summary_["campaign"];
|
||||
std::string campaign_id = load_data_.summary["campaign"];
|
||||
|
||||
for(const config &campaign : game_config_.child_range("campaign"))
|
||||
{
|
||||
|
@ -135,36 +105,43 @@ void loadgame::show_difficulty_dialog()
|
|||
gui2::tcampaign_difficulty difficulty_dlg(campaign);
|
||||
difficulty_dlg.show(video_);
|
||||
|
||||
// Return if canceled, since otherwise difficulty_ will be set to 'CANCEL'
|
||||
// Return if canceled, since otherwise load_data_.difficulty will be set to 'CANCEL'
|
||||
if (difficulty_dlg.get_retval() != gui2::twindow::OK) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
difficulty_ = difficulty_dlg.selected_difficulty();
|
||||
load_data_.difficulty = difficulty_dlg.selected_difficulty();
|
||||
|
||||
// Exit loop
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Called only by play_controller to handle in-game attempts to load. Instead of returning true,
|
||||
// throws a "load_game_exception" to signal a resulting load game request.
|
||||
bool loadgame::load_game()
|
||||
{
|
||||
if (!video_.faked()) {
|
||||
show_dialog();
|
||||
if(!video_.faked()) {
|
||||
if(!gui2::tgame_load::execute(game_config_, load_data_, video_)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(filename_.empty()) {
|
||||
if(load_data_.filename.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (select_difficulty_)
|
||||
show_difficulty_dialog();
|
||||
if(load_data_.select_difficulty) {
|
||||
if(!show_difficulty_dialog()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Confirm the integrity of the file before throwing the exception.
|
||||
// Use the summary in the save_index for this.
|
||||
const config & summary = save_index_manager.get(filename_);
|
||||
const config & summary = save_index_manager.get(load_data_.filename);
|
||||
|
||||
if (summary["corrupt"].to_bool(false)) {
|
||||
gui2::show_error_message(video_,
|
||||
|
@ -176,7 +153,7 @@ bool loadgame::load_game()
|
|||
return false;
|
||||
}
|
||||
|
||||
throw game::load_game_exception(filename_, show_replay_, cancel_orders_, select_difficulty_, difficulty_, true);
|
||||
throw game::load_game_exception(load_data_.filename, load_data_.show_replay, load_data_.cancel_orders, load_data_.select_difficulty, load_data_.difficulty, true);
|
||||
}
|
||||
|
||||
bool loadgame::load_game(
|
||||
|
@ -187,28 +164,33 @@ bool loadgame::load_game(
|
|||
, const std::string& difficulty
|
||||
, bool skip_version_check)
|
||||
{
|
||||
filename_ = filename;
|
||||
difficulty_ = difficulty;
|
||||
select_difficulty_ = select_difficulty;
|
||||
load_data_.filename = filename;
|
||||
load_data_.difficulty = difficulty;
|
||||
load_data_.select_difficulty = select_difficulty;
|
||||
|
||||
if (filename_.empty()){
|
||||
show_dialog();
|
||||
}
|
||||
else{
|
||||
show_replay_ = show_replay;
|
||||
cancel_orders_ = cancel_orders;
|
||||
if(load_data_.filename.empty()){
|
||||
if(!gui2::tgame_load::execute(game_config_, load_data_, video_)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
load_data_.show_replay = show_replay;
|
||||
load_data_.cancel_orders = cancel_orders;
|
||||
}
|
||||
|
||||
if (filename_.empty())
|
||||
if(load_data_.filename.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (select_difficulty_)
|
||||
show_difficulty_dialog();
|
||||
if(load_data_.select_difficulty) {
|
||||
if(!show_difficulty_dialog()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string error_log;
|
||||
read_save_file(filename_, load_config_, &error_log);
|
||||
read_save_file(load_data_.filename, load_data_.load_config, &error_log);
|
||||
|
||||
convert_old_saves(load_config_);
|
||||
convert_old_saves(load_data_.load_config);
|
||||
|
||||
if(!error_log.empty()) {
|
||||
try {
|
||||
|
@ -222,11 +204,11 @@ bool loadgame::load_game(
|
|||
}
|
||||
}
|
||||
|
||||
if (!difficulty_.empty()){
|
||||
load_config_["difficulty"] = difficulty_;
|
||||
if (!load_data_.difficulty.empty()){
|
||||
load_data_.load_config["difficulty"] = load_data_.difficulty;
|
||||
}
|
||||
// read classification to for loading the game_config config object.
|
||||
gamestate_.classification() = game_classification(load_config_);
|
||||
gamestate_.classification() = game_classification(load_data_.load_config);
|
||||
|
||||
if (skip_version_check) {
|
||||
return true;
|
||||
|
@ -285,14 +267,16 @@ bool loadgame::check_version_compatibility(const version_info & save_version, CV
|
|||
|
||||
void loadgame::set_gamestate()
|
||||
{
|
||||
gamestate_.set_data(load_config_);
|
||||
gamestate_.set_data(load_data_.load_config);
|
||||
}
|
||||
|
||||
bool loadgame::load_multiplayer_game()
|
||||
{
|
||||
show_dialog();
|
||||
if(!gui2::tgame_load::execute(game_config_, load_data_, video_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if(filename_.empty()) {
|
||||
if(load_data_.filename.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -303,8 +287,8 @@ bool loadgame::load_multiplayer_game()
|
|||
cursor::setter cur(cursor::WAIT);
|
||||
log_scope("load_game");
|
||||
|
||||
read_save_file(filename_, load_config_, &error_log);
|
||||
copy_era(load_config_);
|
||||
read_save_file(load_data_.filename, load_data_.load_config, &error_log);
|
||||
copy_era(load_data_.load_config);
|
||||
}
|
||||
|
||||
if(!error_log.empty()) {
|
||||
|
@ -314,14 +298,14 @@ bool loadgame::load_multiplayer_game()
|
|||
return false;
|
||||
}
|
||||
|
||||
if(is_replay_save(summary_)) {
|
||||
if(is_replay_save(load_data_.summary)) {
|
||||
gui2::show_transient_message(video_, _("Load Game"), _("Replays are not supported in multiplayer mode."));
|
||||
return false;
|
||||
}
|
||||
|
||||
// We want to verify the game classification before setting the data, so we don't check on
|
||||
// gamestate_.classification() and instead construct a game_classification object manually.
|
||||
if(game_classification(load_config_).campaign_type != game_classification::CAMPAIGN_TYPE::MULTIPLAYER) {
|
||||
if(game_classification(load_data_.load_config).campaign_type != game_classification::CAMPAIGN_TYPE::MULTIPLAYER) {
|
||||
gui2::show_transient_error_message(video_, _("This is not a multiplayer save."));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,29 @@ bool save_game_exists(const std::string& name, compression::format compressed);
|
|||
/** Delete all autosaves of a certain scenario. */
|
||||
void clean_saves(const std::string& label);
|
||||
|
||||
struct load_game_metadata {
|
||||
/** Name of the savefile to be loaded. */
|
||||
std::string filename;
|
||||
|
||||
/** The difficulty the save is meant to be loaded with. */
|
||||
std::string difficulty;
|
||||
|
||||
/** State of the "show_replay" checkbox in the load-game dialog. */
|
||||
bool show_replay;
|
||||
|
||||
/** State of the "cancel_orders" checkbox in the load-game dialog. */
|
||||
bool cancel_orders;
|
||||
|
||||
/** State of the "change_difficulty" checkbox in the load-game dialog. */
|
||||
bool select_difficulty;
|
||||
|
||||
/** Summary config of the save selected in the load game dialog. */
|
||||
config summary;
|
||||
|
||||
/** Config information of the savefile to be loaded. */
|
||||
config load_config;
|
||||
};
|
||||
|
||||
/** The class for loading a savefile. */
|
||||
class loadgame
|
||||
{
|
||||
|
@ -58,9 +81,9 @@ public:
|
|||
void set_gamestate();
|
||||
|
||||
// Getter-methods
|
||||
bool show_replay() const { return show_replay_; }
|
||||
bool cancel_orders() const { return cancel_orders_; }
|
||||
const std::string & filename() const { return filename_; }
|
||||
bool show_replay() const { return load_data_.show_replay; }
|
||||
bool cancel_orders() const { return load_data_.cancel_orders; }
|
||||
const std::string & filename() const { return load_data_.filename; }
|
||||
|
||||
/** GUI Dialog sequence which confirms attempts to load saves from previous game versions. */
|
||||
static bool check_version_compatibility(const version_info & version, CVideo & video);
|
||||
|
@ -71,10 +94,8 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
/** Display the load-game dialog. */
|
||||
void show_dialog();
|
||||
/** Display the difficulty dialog. */
|
||||
void show_difficulty_dialog();
|
||||
bool show_difficulty_dialog();
|
||||
/** Call check_version_compatibility above, using the version of this savefile. */
|
||||
bool check_version_compatibility();
|
||||
/** Copy era information into the snapshot. */
|
||||
|
@ -84,13 +105,8 @@ private:
|
|||
CVideo& video_;
|
||||
|
||||
saved_game& gamestate_; /** Primary output information. */
|
||||
std::string filename_; /** Name of the savefile to be loaded. */
|
||||
std::string difficulty_; /** The difficulty the save is meant to be loaded with. */
|
||||
config load_config_; /** Config information of the savefile to be loaded. */
|
||||
bool show_replay_; /** State of the "show_replay" checkbox in the load-game dialog. */
|
||||
bool cancel_orders_; /** State of the "cancel_orders" checkbox in the load-game dialog. */
|
||||
bool select_difficulty_; /** State of the "change_difficulty" checkbox in the load-game dialog. */
|
||||
config summary_; /** Summary config of the save selected in the load game dialog. */
|
||||
|
||||
load_game_metadata load_data_;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Reference in a new issue