From d7dc0cbdf6a4ddfd5055a92c312c2bf09a8338cb Mon Sep 17 00:00:00 2001 From: Charles Dang Date: Thu, 29 Mar 2018 20:33:00 +1100 Subject: [PATCH] Removed help_manager struct (it will be replaced) This is in preparation for a larger refactor. --- src/editor/controller/editor_controller.cpp | 50 +-- src/editor/controller/editor_controller.hpp | 3 - src/gui/dialogs/title_screen.cpp | 4 - src/help/help.cpp | 22 - src/help/help.hpp | 6 - src/play_controller.cpp | 471 ++++++++++---------- src/play_controller.hpp | 284 ++++++++---- 7 files changed, 441 insertions(+), 399 deletions(-) diff --git a/src/editor/controller/editor_controller.cpp b/src/editor/controller/editor_controller.cpp index 6636ad7d8c1f..dfe6e46b2c03 100644 --- a/src/editor/controller/editor_controller.cpp +++ b/src/editor/controller/editor_controller.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2008 - 2018 by Tomasz Sniatowski - Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -43,9 +43,10 @@ #include "desktop/clipboard.hpp" #include "floating_label.hpp" #include "game_board.hpp" +#include "help/help.hpp" #include "preferences/game.hpp" #include "gettext.hpp" -#include "picture.hpp" +#include "image.hpp" #include "preferences/display.hpp" #include "sound.hpp" #include "units/unit.hpp" @@ -61,42 +62,38 @@ static std::vector saved_windows_; namespace editor { -editor_controller::editor_controller() - : controller_base() +editor_controller::editor_controller(const config &game_config) + : controller_base(game_config) , mouse_handler_base() , quit_confirmation(std::bind(&editor_controller::quit_confirm, this)) , active_menu_(editor::MAP) , reports_(new reports()) - , gui_(new editor_display(*this, *reports_, controller_base::get_theme(game_config_, "editor"))) + , gui_(new editor_display(*this, controller_base::get_theme(game_config, "editor"))) , tods_() , context_manager_(new context_manager(*gui_.get(), game_config_)) , toolkit_(nullptr) , tooltip_manager_() , floating_label_manager_(nullptr) - , help_manager_(nullptr) , do_quit_(false) , quit_mode_(EXIT_ERROR) , music_tracks_() { init_gui(); toolkit_.reset(new editor_toolkit(*gui_.get(), key_, game_config_, *context_manager_.get())); - help_manager_.reset(new help::help_manager(&game_config_)); - context_manager_->locs_ = toolkit_->get_palette_manager()->location_palette_.get(); context_manager_->switch_context(0, true); - init_tods(game_config_); - init_music(game_config_); + init_tods(game_config); + init_music(game_config); get_current_map_context().set_starting_position_labels(gui()); cursor::set(cursor::NORMAL); - gui().create_buttons(); - gui().redraw_everything(); + join(); } void editor_controller::init_gui() { gui_->change_display_context(&get_current_map_context()); preferences::set_preference_display_settings(); - gui_->add_redraw_observer(std::bind(&editor_controller::display_redraw_callback, this, _1)); + //gui_->add_redraw_observer(std::bind(&editor_controller::display_redraw_callback, this, _1)); floating_label_manager_.reset(new font::floating_label_context()); gui().set_draw_coordinates(preferences::editor::draw_hex_coordinates()); gui().set_draw_terrain_codes(preferences::editor::draw_terrain_codes()); @@ -174,10 +171,10 @@ EXIT_STATUS editor_controller::main_loop() while (!do_quit_) { play_slice(); } - } catch (const editor_exception& e) { + } catch (editor_exception& e) { gui2::show_transient_message(_("Fatal error"), e.what()); return EXIT_ERROR; - } catch (const wml_exception& e) { + } catch (wml_exception& e) { e.show(); } return quit_mode_; @@ -190,10 +187,10 @@ void editor_controller::do_screenshot(const std::string& screenshot_filename /* { try { surface screenshot = gui().screenshot(true); - if(screenshot.null() || image::save_image(screenshot, screenshot_filename) != image::save_result::success) { + if(screenshot.null() || !image::save_image(screenshot, screenshot_filename)) { ERR_ED << "Screenshot creation failed!\n"; } - } catch (const wml_exception& e) { + } catch (wml_exception& e) { e.show(); } } @@ -650,10 +647,12 @@ bool editor_controller::do_execute_command(const hotkey::hotkey_command& cmd, in //TODO mark the map as changed sound::play_music_once(music_tracks_[index].id()); get_current_map_context().add_to_playlist(music_tracks_[index]); +#if 0 std::vector items; items.emplace_back("id", "editor-playlist"); std::shared_ptr b = gui_->find_menu_button("menu-playlist"); show_menu(items, b->location().x +1, b->location().y + b->height() +1, false, *gui_); +#endif return true; } case SCHEDULE: @@ -927,10 +926,6 @@ bool editor_controller::do_execute_command(const hotkey::hotkey_command& cmd, in // Side specific ones case HOTKEY_EDITOR_SIDE_NEW: - if(get_current_map_context().teams().size() >= 9) { - size_t new_side_num = get_current_map_context().teams().size() + 1; - toolkit_->get_palette_manager()->location_palette_->add_item(std::to_string(new_side_num)); - } get_current_map_context().new_side(); gui_->init_flags(); return true; @@ -972,17 +967,14 @@ bool editor_controller::do_execute_command(const hotkey::hotkey_command& cmd, in case HOTKEY_EDITOR_DRAW_COORDINATES: gui().set_draw_coordinates(!gui().get_draw_coordinates()); preferences::editor::set_draw_hex_coordinates(gui().get_draw_coordinates()); - gui().invalidate_all(); return true; case HOTKEY_EDITOR_DRAW_TERRAIN_CODES: gui().set_draw_terrain_codes(!gui().get_draw_terrain_codes()); preferences::editor::set_draw_terrain_codes(gui().get_draw_terrain_codes()); - gui().invalidate_all(); return true; case HOTKEY_EDITOR_DRAW_NUM_OF_BITMAPS: gui().set_draw_num_of_bitmaps(!gui().get_draw_num_of_bitmaps()); preferences::editor::set_draw_num_of_bitmaps(gui().get_draw_num_of_bitmaps()); - gui().invalidate_all(); return true; case HOTKEY_EDITOR_REMOVE_LOCATION: { location_palette* lp = dynamic_cast(&toolkit_->get_palette_manager()->active_palette()); @@ -1071,7 +1063,7 @@ void editor_controller::show_menu(const std::vector& items_arg, int xloc active_menu_ = editor::UNIT_FACING; auto pos = items.erase(items.begin()); int dir = 0; - std::generate_n(std::inserter>(items, pos), static_cast(map_location::NDIRECTIONS), [&dir]() -> config { + std::generate_n(std::inserter>(items, pos), int(map_location::NDIRECTIONS), [&dir]() -> config { return config {"label", map_location::write_translated_direction(map_location::DIRECTION(dir++))}; }); } @@ -1107,14 +1099,11 @@ void editor_controller::preferences() { gui_->video().clear_all_help_strings(); gui2::dialogs::preferences_dialog::display(game_config_); - - gui_->redraw_everything(); } void editor_controller::toggle_grid() { preferences::set_grid(!preferences::grid()); - gui_->invalidate_all(); } void editor_controller::unit_description() @@ -1238,7 +1227,6 @@ void editor_controller::refresh_image_cache() void editor_controller::display_redraw_callback(display&) { - set_button_state(); toolkit_->adjust_size(); toolkit_->get_palette_manager()->draw_contents(); get_current_map_context().get_labels().recalculate_labels(); @@ -1314,7 +1302,6 @@ bool editor_controller::left_click(int x, int y, const bool browse) LOG_ED << "Left click action " << hex_clicked << "\n"; editor_action* a = get_mouse_action().click_left(*gui_, x, y); perform_refresh_delete(a, true); - if (a) set_button_state(); return false; } @@ -1329,7 +1316,6 @@ void editor_controller::left_mouse_up(int x, int y, const bool /*browse*/) { editor_action* a = get_mouse_action().up_left(*gui_, x, y); perform_delete(a); - if (a) set_button_state(); toolkit_->set_mouseover_overlay(); context_manager_->refresh_after_action(); } @@ -1344,7 +1330,6 @@ bool editor_controller::right_click(int x, int y, const bool browse) LOG_ED << "Right click action " << hex_clicked << "\n"; editor_action* a = get_mouse_action().click_right(*gui_, x, y); perform_refresh_delete(a, true); - if (a) set_button_state(); return false; } @@ -1361,7 +1346,6 @@ void editor_controller::right_mouse_up(int x, int y, const bool browse) editor_action* a = get_mouse_action().up_right(*gui_, x, y); perform_delete(a); - if (a) set_button_state(); toolkit_->set_mouseover_overlay(); context_manager_->refresh_after_action(); } diff --git a/src/editor/controller/editor_controller.hpp b/src/editor/controller/editor_controller.hpp index 845b6aeb9cec..04789437772a 100644 --- a/src/editor/controller/editor_controller.hpp +++ b/src/editor/controller/editor_controller.hpp @@ -22,7 +22,6 @@ #include "editor/toolkit/editor_toolkit.hpp" #include "controller_base.hpp" -#include "help/help.hpp" #include "hotkey/command_executor.hpp" #include "mouse_handler_base.hpp" #include "tooltips.hpp" @@ -251,8 +250,6 @@ class editor_controller : public controller_base, tooltips::manager tooltip_manager_; std::unique_ptr floating_label_manager_; - std::unique_ptr help_manager_; - /** Quit main loop flag */ bool do_quit_; EXIT_STATUS quit_mode_; diff --git a/src/gui/dialogs/title_screen.cpp b/src/gui/dialogs/title_screen.cpp index 4d769f9b4a48..7f9124f31265 100644 --- a/src/gui/dialogs/title_screen.cpp +++ b/src/gui/dialogs/title_screen.cpp @@ -283,7 +283,6 @@ void title_screen::pre_show(window& win) // Help // register_button(win, "help", hotkey::HOTKEY_HELP, []() { - help::help_manager help_manager(&game_config_manager::get()->game_config()); help::show_help(); }); @@ -334,9 +333,6 @@ void title_screen::pre_show(window& win) // Addons // register_button(win, "addons", hotkey::TITLE_SCREEN__ADDONS, []() { - // NOTE: we need the help_manager to get access to the Add-ons section in the game help! - help::help_manager help_manager(&game_config_manager::get()->game_config()); - if(manage_addons()) { game_config_manager::get()->reload_changed_game_config(); } diff --git a/src/help/help.cpp b/src/help/help.cpp index e8203bfa69a2..3650a76ad3db 100644 --- a/src/help/help.cpp +++ b/src/help/help.cpp @@ -74,28 +74,6 @@ void show_unit_description(const unit_type& t) } } -extern config dummy_cfg; - -help_manager::help_manager(const config* cfg) //, gamemap *_map) -{ - game_cfg = cfg == nullptr ? &dummy_cfg : cfg; - // map = _map; -} - -help_manager::~help_manager() -{ - game_cfg = nullptr; - - // map = nullptr; - default_toplevel.clear(); - hidden_sections.clear(); - - // These last numbers must be reset so that the content is regenerated. - // Upon next start. - last_num_encountered_units = -1; - last_num_encountered_terrains = -1; -} - void show_help(const std::string& show_topic) { show_help(default_toplevel, show_topic); diff --git a/src/help/help.hpp b/src/help/help.hpp index af0663b9da71..a8c4f4a42351 100644 --- a/src/help/help.hpp +++ b/src/help/help.hpp @@ -23,12 +23,6 @@ class unit_type; namespace help { -struct help_manager -{ - help_manager(const config* game_config); - ~help_manager(); -}; - struct section; void init_help(); diff --git a/src/play_controller.cpp b/src/play_controller.cpp index d609cee60f9d..11c4f8f43d77 100644 --- a/src/play_controller.cpp +++ b/src/play_controller.cpp @@ -1,7 +1,7 @@ /* Copyright (C) 2006 - 2018 by Joerg Hinrichs wesnoth playlevel Copyright (C) 2003 by David White - Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,30 +26,31 @@ #include "actions/vision.hpp" #include "ai/manager.hpp" #include "ai/testing.hpp" -#include "preferences/credentials.hpp" #include "display_chat_manager.hpp" #include "formula/string_utils.hpp" #include "game_events/menu_item.hpp" #include "game_events/pump.hpp" -#include "preferences/game.hpp" #include "game_state.hpp" -#include "hotkey/hotkey_item.hpp" -#include "hotkey/hotkey_handler.hpp" -#include "map/label.hpp" #include "gettext.hpp" +#include "gui/dialogs/game_ui.hpp" #include "gui/dialogs/loading_screen.hpp" #include "gui/dialogs/transient_message.hpp" #include "hotkey/command_executor.hpp" +#include "hotkey/hotkey_handler.hpp" +#include "hotkey/hotkey_item.hpp" #include "log.hpp" +#include "map/label.hpp" #include "pathfind/teleport.hpp" +#include "preferences/credentials.hpp" #include "preferences/display.hpp" +#include "preferences/game.hpp" #include "random.hpp" #include "replay.hpp" #include "reports.hpp" #include "resources.hpp" -#include "savegame.hpp" -#include "saved_game.hpp" #include "save_blocker.hpp" +#include "saved_game.hpp" +#include "savegame.hpp" #include "scripting/game_lua_kernel.hpp" #include "scripting/plugins/context.hpp" #include "sound.hpp" @@ -58,15 +59,14 @@ #include "synced_context.hpp" #include "terrain/type_data.hpp" #include "tooltips.hpp" -#include "units/unit.hpp" #include "units/id.hpp" -#include "whiteboard/manager.hpp" - +#include "units/unit.hpp" #include "utils/functional.hpp" +#include "whiteboard/manager.hpp" static lg::log_domain log_aitesting("aitesting"); #define LOG_AIT LOG_STREAM(info, log_aitesting) -//If necessary, this define can be replaced with `#define LOG_AIT std::cout` to restore previous behavior +// If necessary, this define can be replaced with `#define LOG_AIT std::cout` to restore previous behavior static lg::log_domain log_engine("engine"); #define LOG_NG LOG_STREAM(info, log_engine) @@ -87,25 +87,22 @@ static lg::log_domain log_engine_enemies("engine/enemies"); static void copy_persistent(const config& src, config& dst) { static const std::set attrs { - "description", - "name", - "victory_when_enemies_defeated", - "remove_from_carryover_on_defeat", - "disallow_recall", - "experience_modifier", - "require_scenario"}; - - static const std::set tags { - "terrain_graphics", - "lua"}; - - for (const std::string& attr : attrs) - { + "description", + "name", + "victory_when_enemies_defeated", + "remove_from_carryover_on_defeat", + "disallow_recall", + "experience_modifier", + "require_scenario" + }; + + static const std::set tags{"terrain_graphics", "lua"}; + + for(const std::string& attr : attrs) { dst[attr] = src[attr]; } - for (const std::string& tag : tags) - { + for(const std::string& tag : tags) { dst.append_children(src, tag); } } @@ -128,9 +125,12 @@ static void clear_resources() resources::classification = nullptr; } -play_controller::play_controller(const config& level, saved_game& state_of_game, - const ter_data_cache& tdata, bool skip_replay) - : controller_base() +play_controller::play_controller(const config& level, + saved_game& state_of_game, + const config& game_config, + const ter_data_cache& tdata, + bool skip_replay) + : controller_base(game_config) , observer() , quit_confirmation() , ticks_(SDL_GetTicks()) @@ -142,18 +142,17 @@ play_controller::play_controller(const config& level, saved_game& state_of_game, , whiteboard_manager_() , plugins_context_() , labels_manager_() - , help_manager_(&game_config_) , mouse_handler_(nullptr, *this) - , menu_handler_(nullptr, *this) + , menu_handler_(nullptr, *this, game_config) , hotkey_handler_(new hotkey_handler(*this, saved_game_)) , soundsources_manager_() , persist_() , gui_() + , ui_() , xp_mod_(new unit_experience_accelerator(level["experience_modifier"].to_int(100))) , statistics_context_(new statistics::scenario_context(level["name"])) , replay_(new replay(state_of_game.get_replay())) , skip_replay_(skip_replay) - , skip_story_(state_of_game.skip_story()) , linger_(false) , init_side_done_now_(false) , map_start_() @@ -170,17 +169,20 @@ play_controller::play_controller(const config& level, saved_game& state_of_game, resources::controller = this; resources::persist = &persist_; resources::recorder = replay_.get(); - resources::classification = &saved_game_.classification(); persist_.start_transaction(); + join(); + game_config::add_color_info(level); + hotkey::deactivate_all_scopes(); hotkey::set_scope_active(hotkey::SCOPE_GAME); + try { init(level); - } catch (...) { + } catch(...) { clear_resources(); throw; } @@ -218,6 +220,7 @@ void play_controller::init(const config& level) gamestate_->ai_manager_.add_observer(this); gamestate_->init(level, *this); + resources::tunnels = gamestate().pathfind_manager_.get(); LOG_NG << "initializing whiteboard..." << (SDL_GetTicks() - ticks()) << std::endl; @@ -235,22 +238,27 @@ void play_controller::init(const config& level) LOG_NG << "building terrain rules... " << (SDL_GetTicks() - ticks()) << std::endl; gui2::dialogs::loading_screen::progress(loading_stage::build_terrain); - gui_.reset(new game_display(gamestate().board_, whiteboard_manager_, *gamestate().reports_, theme_cfg, level)); + + gui_.reset(new game_display(gamestate().board_, whiteboard_manager_, theme_cfg, level)); + map_start_ = map_location(level.child_or_empty("display").child_or_empty("location")); - if (!gui_->video().faked()) { - if (saved_game_.mp_settings().mp_countdown) - gui_->get_theme().modify_label("time-icon", _ ("time left for current turn")); - else - gui_->get_theme().modify_label("time-icon", _ ("current local time")); + + if(!gui_->video().faked()) { + if(saved_game_.mp_settings().mp_countdown) { + gui_->get_theme().modify_label("time-icon", _("time left for current turn")); + } else { + gui_->get_theme().modify_label("time-icon", _("current local time")); + } } gui2::dialogs::loading_screen::progress(loading_stage::init_display); + mouse_handler_.set_gui(gui_.get()); menu_handler_.set_gui(gui_.get()); LOG_NG << "done initializing display... " << (SDL_GetTicks() - ticks()) << std::endl; - LOG_NG << "building gamestate to gui and whiteboard... " << (SDL_GetTicks() - ticks()) << std::endl; + // This *needs* to be created before the show_intro and show_map_scene // as that functions use the manager state_of_game // Has to be done before registering any events! @@ -259,15 +267,12 @@ void play_controller::init(const config& level) if(gamestate().first_human_team_ != -1) { gui_->set_team(gamestate().first_human_team_); - } - else if(is_observer()) { + } else if(is_observer()) { // Find first team that is allowed to be observed. // If not set here observer would be without fog until // the first turn of observable side - for (const team& t : gamestate().board_.teams()) - { - if (!t.get_disallow_observers()) - { + for(const team& t : gamestate().board_.teams()) { + if(!t.get_disallow_observers()) { gui_->set_team(t.side() - 1); } } @@ -275,18 +280,33 @@ void play_controller::init(const config& level) init_managers(); gui2::dialogs::loading_screen::progress(loading_stage::start_game); - //loadscreen_manager->reset(); + + // loadscreen_manager->reset(); gamestate().gamedata_.set_phase(game_data::PRELOAD); gamestate().lua_kernel_->load_game(level); plugins_context_.reset(new plugins_context("Game")); - plugins_context_->set_callback("save_game", [this](const config& cfg) { save_game_auto(cfg["filename"]); }, true); - plugins_context_->set_callback("save_replay", [this](const config& cfg) { save_replay_auto(cfg["filename"]); }, true); + plugins_context_->set_callback( + "save_game", [this](const config& cfg) { save_game_auto(cfg["filename"]); }, true); + plugins_context_->set_callback( + "save_replay", [this](const config& cfg) { save_replay_auto(cfg["filename"]); }, true); plugins_context_->set_callback("quit", throw_end_level(), false); plugins_context_->set_accessor_string("scenario_name", [this](config) { return get_scenario_name(); }); }); - //Do this after the loadingscreen, so that ita happens in the main thread. + + // Do this after the loadingscreen, so that ita happens in the main thread. gui_->join(); + + initialize_and_show_ui(); +} + +void play_controller::initialize_and_show_ui() +{ + // Set member in the base class + ui_.reset(new gui2::dialogs::game_ui()); + assert(ui_); + + ui_->show(true); } void play_controller::reset_gamestate(const config& level, int replay_pos) @@ -302,9 +322,9 @@ void play_controller::reset_gamestate(const config& level, int replay_pos) gui_->labels().set_team(nullptr); - /* First destroy the old game state, then create the new one. - This is necessary to ensure that while the old AI manager is being destroyed, - all its member objects access the old manager instead of the new. */ + // First destroy the old game state, then create the new one. + // This is necessary to ensure that while the old AI manager is being destroyed, + // all its member objects access the old manager instead of the new. gamestate_.reset(); gamestate_.reset(new game_state(level, *this, tdata_)); resources::gameboard = &gamestate().board_; @@ -320,9 +340,11 @@ void play_controller::reset_gamestate(const config& level, int replay_pos) gamestate().set_game_display(gui_.get()); resources::tunnels = gamestate().pathfind_manager_.get(); - gui_->reset_reports(*gamestate().reports_); + //gui_->reset_reports(*gamestate().reports_); gui_->change_display_context(&gamestate().board_); + saved_game_.get_replay().set_pos(replay_pos); + gamestate().gamedata_.set_phase(game_data::PRELOAD); gamestate().lua_kernel_->load_game(level); } @@ -341,7 +363,7 @@ void play_controller::init_managers() void play_controller::fire_preload() { // Run initialization scripts, even if loading from a snapshot. - gamestate().gamedata_.get_variable("turn_number") = static_cast(turn()); + gamestate().gamedata_.get_variable("turn_number") = int(turn()); pump().fire("preload"); } @@ -354,20 +376,14 @@ void play_controller::fire_prestart() // Fire these right before prestart events, to catch only the units sides // have started with. - for (const unit& u : gamestate().board_.units()) { + for(const unit& u : gamestate().board_.units()) { pump().fire("unit_placed", map_location(u.get_location())); } pump().fire("prestart"); - // prestart event may modify start turn with WML, reflect any changes. - gamestate().gamedata_.get_variable("turn_number") = static_cast(turn()); -} -void play_controller::refresh_objectives() const -{ - const config cfg("side", gui_->viewing_side()); - gamestate().lua_kernel_->run_wml_action("show_objectives", vconfig(cfg), - game_events::queued_event("_from_interface", "", map_location(), map_location(), config())); + // prestart event may modify start turn with WML, reflect any changes. + gamestate().gamedata_.get_variable("turn_number") = int(turn()); } void play_controller::fire_start() @@ -375,19 +391,16 @@ void play_controller::fire_start() gamestate().gamedata_.set_phase(game_data::START); pump().fire("start"); - skip_story_ = false; // Show [message]s from now on even with --campaign-skip-story - // start event may modify start turn with WML, reflect any changes. - gamestate().gamedata_.get_variable("turn_number") = static_cast(turn()); + gamestate().gamedata_.get_variable("turn_number") = int(turn()); - refresh_objectives(); check_objectives(); - // prestart and start events may modify the initial gold amount, - // reflect any changes. - for (team& tm : gamestate().board_.teams_) - { + + // prestart and start events may modify the initial gold amount, reflect any changes. + for(team& tm : gamestate().board_.teams_) { tm.set_start_gold(tm.gold()); } + gamestate_->init_side_done() = false; gamestate().gamedata_.set_phase(game_data::PLAY); } @@ -403,9 +416,8 @@ void play_controller::init_side_begin() mouse_handler_.set_side(current_side()); // If we are observers we move to watch next team if it is allowed - if ((is_observer() && !current_team().get_disallow_observers()) - || (current_team().is_local_human() && !this->is_replay())) - { + if((is_observer() && !current_team().get_disallow_observers()) + || (current_team().is_local_human() && !this->is_replay())) { update_gui_to_player(current_side() - 1); } @@ -421,18 +433,19 @@ void play_controller::maybe_do_init_side() // For all other sides it is recorded in replay and replay handler has to handle // calling do_init_side() functions. // - if (gamestate_->init_side_done()) { - // We already executed do_init_side this can for example happe if we reload a game, + if(gamestate_->init_side_done()) { + // We already executed do_init_side this can for example happen if we reload a game, // but also if we changed control of a side during it's turn return; } - if (!current_team().is_local()) { + + if(!current_team().is_local()) { // We are in a mp game and execute do_init_side as soon as we receive [init_side] from the current player // (see replay.cpp) return; } - if (is_replay()) { + if(is_replay()) { // We are in a replay and execute do_init_side as soon as we reach the next [init_side] in the replay data // (see replay.cpp) return; @@ -446,6 +459,7 @@ void play_controller::do_init_side() { set_scontext_synced sync; log_scope("player turn"); + // In case we might end up calling sync:network during the side turn events, // and we don't want do_init_side to be called when a player drops. gamestate_->init_side_done() = true; @@ -457,8 +471,7 @@ void play_controller::do_init_side() gamestate().gamedata_.get_variable("side_number") = current_side(); // We might have skipped some sides because they were empty so it is not enough to check for side_num==1 - if(!gamestate().tod_manager_.has_turn_event_fired()) - { + if(!gamestate().tod_manager_.has_turn_event_fired()) { pump().fire("turn_" + turn_num); pump().fire("new_turn"); gamestate().tod_manager_.turn_event_fired(); @@ -473,31 +486,20 @@ void play_controller::do_init_side() // and the player should get income now. // Healing/income happen if it's not the first turn of processing, // or if we are loading a game. - if (turn() > 1) { + if(turn() > 1) { gamestate().board_.new_turn(current_side()); current_team().new_turn(); // If the expense is less than the number of villages owned // times the village support capacity, // then we don't have to pay anything at all - int expense = gamestate().board_.side_upkeep(current_side()) - - current_team().support(); + int expense = gamestate().board_.side_upkeep(current_side()) - current_team().support(); if(expense > 0) { current_team().spend_gold(expense); } - } - if (do_healing()) { + calculate_healing(current_side(), !is_skipping_replay()); } - // Do healing on every side turn except the very first side turn. - // (1.14 and earlier did healing whenever turn >= 2.) - set_do_healing(true); - // Set resting now after the healing has been done. - for(unit &patient : resources::gameboard->units()) { - if(patient.side() == current_side()) { - patient.set_resting(true); - } - } // Prepare the undo stack. undo_stack().new_side_turn(current_side()); @@ -509,6 +511,7 @@ void play_controller::do_init_side() // Make sure vision is accurate. actions::clear_shroud(current_side(), true); + init_side_end(); check_victory(); sync.do_final_checkup(); @@ -518,16 +521,14 @@ void play_controller::init_side_end() { const time_of_day& tod = gamestate().tod_manager_.get_time_of_day(); - if (current_side() == 1 || !init_side_done_now_) + if(current_side() == 1 || !init_side_done_now_) { sound::play_sound(tod.sounds, sound::SOUND_SOURCES); - - if (!is_skipping_replay()){ - gui_->invalidate_all(); } - if (!is_skipping_replay() && current_team().get_scroll_to_leader() && !map_start_.valid()){ - gui_->scroll_to_leader(current_side(), game_display::ONSCREEN,false); + if(!is_skipping_replay() && current_team().get_scroll_to_leader() && !map_start_.valid()) { + gui_->scroll_to_leader(current_side(), game_display::ONSCREEN, false); } + map_start_ = map_location(); whiteboard_manager_->on_init_side(); } @@ -541,7 +542,7 @@ config play_controller::to_config() const gui_->write(cfg.add_child("display")); - //Write the soundsources. + // Write the soundsources. soundsources_manager_->write_sourcespecs(cfg); gui_->labels().write(cfg); @@ -554,11 +555,12 @@ void play_controller::finish_side_turn() { whiteboard_manager_->on_finish_side_turn(current_side()); - { //Block for set_scontext_synced + { // Block for set_scontext_synced set_scontext_synced sync(1); // Ending the turn commits all moves. undo_stack().clear(); gamestate().board_.end_turn(current_side()); + const std::string turn_num = std::to_string(turn()); const std::string side_num = std::to_string(current_side()); @@ -566,9 +568,10 @@ void play_controller::finish_side_turn() actions::clear_shroud(current_side()); pump().fire("side_turn_end"); - pump().fire("side_"+ side_num + "_turn_end"); + pump().fire("side_" + side_num + "_turn_end"); pump().fire("side_turn_" + turn_num + "_end"); pump().fire("side_" + side_num + "_turn_" + turn_num + "_end"); + // This is where we refog, after all of a side's events are done. actions::recalculate_fog(current_side()); check_victory(); @@ -576,6 +579,7 @@ void play_controller::finish_side_turn() } mouse_handler_.deselect_hex(); + resources::gameboard->unit_id_manager().reset_fake(); gamestate_->init_side_done() = false; } @@ -583,20 +587,23 @@ void play_controller::finish_turn() { set_scontext_synced sync(2); const std::string turn_num = std::to_string(turn()); + pump().fire("turn_end"); pump().fire("turn_" + turn_num + "_end"); + sync.do_final_checkup(); } bool play_controller::enemies_visible() const { // If we aren't using fog/shroud, this is easy :) - if(current_team().uses_fog() == false && current_team().uses_shroud() == false) + if(current_team().uses_fog() == false && current_team().uses_shroud() == false) { return true; + } // See if any enemies are visible - for (const unit& u : gamestate().board_.units()) { - if (current_team().is_enemy(u.side()) && !gui_->fogged(u.get_location())) { + for(const unit& u : gamestate().board_.units()) { + if(current_team().is_enemy(u.side()) && !gui_->fogged(u.get_location())) { return true; } } @@ -604,39 +611,8 @@ bool play_controller::enemies_visible() const return false; } -void play_controller::enter_textbox() -{ - if(menu_handler_.get_textbox().active() == false) { - return; - } - - const std::string str = menu_handler_.get_textbox().box()->text(); - const unsigned int team_num = current_side(); - events::mouse_handler& mousehandler = mouse_handler_; - - switch(menu_handler_.get_textbox().mode()) { - case gui::TEXTBOX_SEARCH: - menu_handler_.do_search(str); - menu_handler_.get_textbox().close(*gui_); - break; - case gui::TEXTBOX_MESSAGE: - menu_handler_.do_speak(); - menu_handler_.get_textbox().close(*gui_); //need to close that one after executing do_speak() ! - break; - case gui::TEXTBOX_COMMAND: - menu_handler_.get_textbox().close(*gui_); - menu_handler_.do_command(str); - break; - case gui::TEXTBOX_AI: - menu_handler_.get_textbox().close(*gui_); - menu_handler_.do_ai_formula(str, team_num, mousehandler); - break; - default: - menu_handler_.get_textbox().close(*gui_); - ERR_DP << "unknown textbox mode" << std::endl; - } -} - +// TODO: implement in GUI2 command console dialog +#if 0 void play_controller::tab() { gui::TEXTBOX_MODE mode = menu_handler_.get_textbox().mode(); @@ -648,7 +624,7 @@ void play_controller::tab() for (const unit& u : gamestate().board_.units()){ const map_location& loc = u.get_location(); if(!gui_->fogged(loc) && - !(gamestate().board_.teams()[gui_->viewing_team()].is_enemy(u.side()) && u.invisible(loc))) + !(gamestate().board_.teams()[gui_->viewing_team()].is_enemy(u.side()) && u.invisible(loc, gui_->get_disp_context()))) dictionary.insert(u.name()); } //TODO List map labels @@ -696,6 +672,7 @@ void play_controller::tab() menu_handler_.get_textbox().tab(dictionary); } +#endif team& play_controller::current_team() { @@ -714,9 +691,9 @@ static int modulo(int num, int mod, int min) { assert(mod > 0); int n = (num - min) % mod; - if (n < 0) + if(n < 0) n += mod; - //n is now in [0, mod) + // n is now in [0, mod) n = n + min; return n; // the following properties are easy to verify: @@ -729,15 +706,14 @@ bool play_controller::is_team_visible(int team_num, bool observer) const const team& t = gamestate().board_.get_team(team_num); if(observer) { return !t.get_disallow_observers() && !t.is_empty(); - } - else { + } else { return t.is_local_human() && !t.is_idle(); } } int play_controller::find_last_visible_team() const { - assert(current_side() <= static_cast(gamestate().board_.teams().size())); + assert(current_side() <= int(gamestate().board_.teams().size())); const int num_teams = gamestate().board_.teams().size(); const bool is_observer = this->is_observer(); @@ -775,25 +751,9 @@ game_display& play_controller::get_display() return *gui_; } -bool play_controller::have_keyboard_focus() -{ - return !menu_handler_.get_textbox().active(); -} - -void play_controller::process_focus_keydown_event(const SDL_Event& event) -{ - if(event.key.keysym.sym == SDLK_ESCAPE) { - menu_handler_.get_textbox().close(*gui_); - } else if(event.key.keysym.sym == SDLK_TAB) { - tab(); - } else if(event.key.keysym.sym == SDLK_RETURN || event.key.keysym.sym == SDLK_KP_ENTER) { - enter_textbox(); - } -} - void play_controller::process_keydown_event(const SDL_Event& event) { - if (event.key.keysym.sym == SDLK_TAB) { + if(event.key.keysym.sym == SDLK_TAB) { whiteboard_manager_->set_invert_behavior(true); } } @@ -803,8 +763,7 @@ void play_controller::process_keyup_event(const SDL_Event& event) // If the user has pressed 1 through 9, we want to show // how far the unit can move in that many turns if(event.key.keysym.sym >= '1' && event.key.keysym.sym <= '9') { - const int new_path_turns = (event.type == SDL_KEYDOWN) ? - event.key.keysym.sym - '1' : 0; + const int new_path_turns = (event.type == SDL_KEYDOWN) ? event.key.keysym.sym - '1' : 0; if(new_path_turns != mouse_handler_.get_path_turns()) { mouse_handler_.set_path_turns(new_path_turns); @@ -815,25 +774,24 @@ void play_controller::process_keyup_event(const SDL_Event& event) // if it's not the unit's turn, we reset its moves unit_movement_resetter move_reset(*u, u->side() != current_side()); - mouse_handler_.set_current_paths(pathfind::paths(*u, false, - true, gamestate().board_.teams_[gui_->viewing_team()], - mouse_handler_.get_path_turns())); + mouse_handler_.set_current_paths(pathfind::paths(*u, false, true, + gamestate().board_.teams_[gui_->viewing_team()], mouse_handler_.get_path_turns())); gui_->highlight_reach(mouse_handler_.current_paths()); } else { mouse_handler_.select_hex(mouse_handler_.get_selected_hex(), false, false, false); } - } - } else if (event.key.keysym.sym == SDLK_TAB) { + } else if(event.key.keysym.sym == SDLK_TAB) { CKey keys; - if (!keys[SDLK_TAB]) { + if(!keys[SDLK_TAB]) { whiteboard_manager_->set_invert_behavior(false); } } } -replay& play_controller::get_replay() { +replay& play_controller::get_replay() +{ assert(replay_); return *replay_.get(); } @@ -850,7 +808,7 @@ void play_controller::save_game() savegame::ingame_savegame save(saved_game_, preferences::save_compression_format()); save.save_game_interactive("", savegame::savegame::OK_CANCEL); } else { - save_blocker::on_unblock(this,&play_controller::save_game); + save_blocker::on_unblock(this, &play_controller::save_game); } } @@ -872,7 +830,7 @@ void play_controller::save_replay() savegame::replay_savegame save(saved_game_, preferences::save_compression_format()); save.save_game_interactive("", savegame::savegame::OK_CANCEL); } else { - save_blocker::on_unblock(this,&play_controller::save_replay); + save_blocker::on_unblock(this, &play_controller::save_replay); } } @@ -891,7 +849,7 @@ void play_controller::save_map() save_blocker::save_unblocker unblocker; menu_handler_.save_map(); } else { - save_blocker::on_unblock(this,&play_controller::save_map); + save_blocker::on_unblock(this, &play_controller::save_map); } } @@ -926,8 +884,12 @@ bool play_controller::can_redo() const const std::string& play_controller::select_music(bool victory) const { const std::vector& music_list = victory - ? (gamestate_->get_game_data()->get_victory_music().empty() ? game_config::default_victory_music : gamestate_->get_game_data()->get_victory_music()) - : (gamestate_->get_game_data()->get_defeat_music().empty() ? game_config::default_defeat_music : gamestate_->get_game_data()->get_defeat_music()); + ? (gamestate_->get_game_data()->get_victory_music().empty() + ? game_config::default_victory_music + : gamestate_->get_game_data()->get_victory_music()) + : (gamestate_->get_game_data()->get_defeat_music().empty() + ? game_config::default_defeat_music + : gamestate_->get_game_data()->get_defeat_music()); if(music_list.empty()) { // Since this function returns a reference, we can't return a temporary empty string. @@ -935,35 +897,39 @@ const std::string& play_controller::select_music(bool victory) const return empty_str; } - return music_list[randomness::rng::default_instance().get_random_int(0, music_list.size()-1)]; + return music_list[randomness::rng::default_instance().get_random_int(0, music_list.size() - 1)]; } void play_controller::check_victory() { - if(linger_) - { + if(linger_) { return; } - if (is_regular_game_end()) { + if(is_regular_game_end()) { return; } + bool continue_level, found_player, found_network_player, invalidate_all; std::set not_defeated; - gamestate().board_.check_victory(continue_level, found_player, found_network_player, invalidate_all, not_defeated, remove_from_carryover_on_defeat_); - - if (invalidate_all) { - gui_->invalidate_all(); - } + gamestate().board_.check_victory( + continue_level, + found_player, + found_network_player, + invalidate_all, + not_defeated, + remove_from_carryover_on_defeat_ + ); - if (continue_level) { - return ; + if(continue_level) { + return; } - if (found_player || found_network_player) { + if(found_player || found_network_player) { pump().fire("enemies_defeated"); - if (is_regular_game_end()) { + + if(is_regular_game_end()) { return; } } @@ -972,24 +938,30 @@ void play_controller::check_victory() DBG_EE << "found_player: " << found_player << std::endl; DBG_EE << "found_network_player: " << found_network_player << std::endl; - if (!victory_when_enemies_defeated_ && (found_player || found_network_player)) { + if(!victory_when_enemies_defeated_ && (found_player || found_network_player)) { // This level has asked not to be ended by this condition. return; } - if (gui_->video().non_interactive()) { + if(gui_->video().non_interactive()) { LOG_AIT << "winner: "; - for (unsigned l : not_defeated) { + + for(unsigned l : not_defeated) { std::string ai = ai::manager::get_singleton().get_active_ai_identifier_for_side(l); - if (ai.empty()) ai = "default ai"; + if(ai.empty()) { + ai = "default ai"; + } + LOG_AIT << l << " (using " << ai << ") "; } + LOG_AIT << std::endl; ai_testing::log_victory(not_defeated); } DBG_EE << "throwing end level exception..." << std::endl; - //Also proceed to the next scenario when another player survived. + + // Also proceed to the next scenario when another player survived. end_level_data el_data; el_data.proceed_to_next_level = found_player || found_network_player; el_data.is_victory = found_player; @@ -998,10 +970,13 @@ void play_controller::check_victory() void play_controller::process_oos(const std::string& msg) const { - if (gui_->video().non_interactive()) { + if(gui_->video().non_interactive()) { throw game::game_error(msg); } - if (game_config::ignore_replay_errors) return; + + if(game_config::ignore_replay_errors) { + return; + } std::stringstream message; message << _("The game is out of sync. It might not make much sense to continue. Do you want to save your game?"); @@ -1016,7 +991,6 @@ void play_controller::update_gui_to_player(const int team_index, const bool obse { gui_->set_team(team_index, observe); gui_->recalculate_minimap(); - gui_->invalidate_all(); } void play_controller::do_autosave() @@ -1035,7 +1009,7 @@ void play_controller::do_consolesave(const std::string& filename) void play_controller::update_savegame_snapshot() const { - //note: this writes to level_ if this is not a replay. + // note: this writes to level_ if this is not a replay. this->saved_game_.set_snapshot(to_config()); } @@ -1069,6 +1043,7 @@ bool play_controller::is_browsing() const if(linger_ || !gamestate_->init_side_done() || gamestate().gamedata_.phase() != game_data::PLAY) { return true; } + const team& t = current_team(); return !t.is_local_human() || !t.is_proxy_human(); } @@ -1078,12 +1053,10 @@ void play_controller::play_slice_catch() if(should_return_to_play_side()) { return; } - try - { + + try { play_slice(); - } - catch(const return_to_play_side_exception&) - { + } catch(const return_to_play_side_exception&) { assert(should_return_to_play_side()); } } @@ -1092,8 +1065,7 @@ void play_controller::start_game() { fire_preload(); - if(!gamestate().start_event_fired_) - { + if(!gamestate().start_event_fired_) { gamestate().start_event_fired_ = true; map_start_ = map_location(); resources::recorder->add_start_if_not_there_yet(); @@ -1102,11 +1074,12 @@ void play_controller::start_game() set_scontext_synced sync; fire_prestart(); - if (is_regular_game_end()) { + + if(is_regular_game_end()) { return; } - for (const team& t : gamestate().board_.teams()) { + for(const team& t : gamestate().board_.teams()) { actions::clear_shroud(t.side(), false, false); } @@ -1114,21 +1087,21 @@ void play_controller::start_game() LOG_NG << "first_time..." << (is_skipping_replay() ? "skipping" : "no skip") << "\n"; fire_start(); - if (is_regular_game_end()) { + + if(is_regular_game_end()) { return; } + sync.do_final_checkup(); gui_->recalculate_minimap(); + // Initialize countdown clock. - for (const team& t : gamestate().board_.teams()) - { - if (saved_game_.mp_settings().mp_countdown) { + for(const team& t : gamestate().board_.teams()) { + if(saved_game_.mp_settings().mp_countdown) { t.set_countdown_time(1000 * saved_game_.mp_settings().mp_countdown_init_time); } } - } - else - { + } else { init_gui(); gamestate().gamedata_.set_phase(game_data::PLAY); gui_->recalculate_minimap(); @@ -1138,25 +1111,24 @@ void play_controller::start_game() bool play_controller::can_use_synced_wml_menu() const { const team& viewing_team = get_teams_const()[gui_->viewing_team()]; - return gui_->viewing_team() == gui_->playing_team() && !events::commands_disabled && viewing_team.is_local_human() && !is_lingering() && !is_browsing(); + return gui_->viewing_team() == gui_->playing_team() && !events::commands_disabled && viewing_team.is_local_human() + && !is_lingering() && !is_browsing(); } std::set play_controller::all_players() const { std::set res = gui_->observers(); - for (const team& t : get_teams_const()) - { - if (t.is_human()) { + for(const team& t : get_teams_const()) { + if(t.is_human()) { res.insert(t.current_player()); } } + return res; } void play_controller::play_side() { - //check for team-specific items in the scenario - gui_->parse_team_overlays(); do { update_viewing_player(); { @@ -1166,10 +1138,11 @@ void play_controller::play_side() return; } } + // This flag can be set by derived classes (in overridden functions). player_type_changed_ = false; - statistics::reset_turn_stats(gamestate().board_.get_team(current_side()).save_id_or_number()); + statistics::reset_turn_stats(gamestate().board_.get_team(current_side()).save_id()); play_side_impl(); @@ -1177,9 +1150,9 @@ void play_controller::play_side() return; } - } while (player_type_changed_); - // Keep looping if the type of a team (human/ai/networked) - // has changed mid-turn + } while(player_type_changed_); + + // Keep looping if the type of a team (human/ai/networked) has changed mid-turn sync_end_turn(); } @@ -1187,7 +1160,6 @@ void play_controller::play_turn() { whiteboard_manager_->on_gamestate_change(); gui_->new_turn(); - gui_->invalidate_game_status(); LOG_NG << "turn: " << turn() << "\n"; @@ -1198,14 +1170,15 @@ void play_controller::play_turn() int last_player_number = gamestate_->player_number_; int next_player_number = gamestate_->next_player_number_; - while(gamestate_->player_number_ <= static_cast(gamestate().board_.teams().size())) { + while(gamestate_->player_number_ <= int(gamestate().board_.teams().size())) { gamestate_->next_player_number_ = gamestate_->player_number_ + 1; next_player_number = gamestate_->next_player_number_; last_player_number = gamestate_->player_number_; // If a side is empty skip over it. - if (!current_team().is_empty()) { + if(!current_team().is_empty()) { init_side_begin(); + if(gamestate_->init_side_done()) { // This is the case in a reloaded game where the side was initialized before saving the game. init_side_end(); @@ -1213,29 +1186,34 @@ void play_controller::play_turn() ai_testing::log_turn_start(current_side()); play_side(); - //ignore any changes to next_player_number_ that happen after the [end_turn] is sended to the server, otherwise we will get OOS. + // ignore any changes to next_player_number_ that happen after the [end_turn] is sent to the server, + // otherwise we will get OOS. next_player_number = gamestate_->next_player_number_; - assert(next_player_number <= 2 * static_cast(gamestate().board_.teams().size())); + assert(next_player_number <= 2 * int(gamestate().board_.teams().size())); if(is_regular_game_end()) { return; } - //note: play_side() send the [end_turn] to the sever and finish_side_turn() callsie the side turn end events. - // this means that during the side turn end events the clients think it is still the last sides turn while - // the server thinks that it is already the next plyers turn. i don'T think this is a problem though. + // note: play_side() send the [end_turn] to the sever and finish_side_turn() calls the side turn end + // events. + // this means that during the side turn end events the clients think it is still the last sides turn + // while the server thinks that it is already the next plyers turn. i don'T think this is a problem + // though. finish_side_turn(); + if(is_regular_game_end()) { return; } + if(gui_->video().non_interactive()) { - LOG_AIT << " Player " << current_side() << ": " << - current_team().villages().size() << " Villages" << - std::endl; + LOG_AIT << " Player " << current_side() << ": " << current_team().villages().size() << " Villages" + << std::endl; ai_testing::log_turn_end(current_side()); } } gamestate_->player_number_ = next_player_number; } + // If the loop exits due to the last team having been processed. gamestate_->player_number_ = last_player_number; @@ -1244,7 +1222,7 @@ void play_controller::play_turn() // Time has run out check_time_over(); - if (!is_regular_game_end()) { + if(!is_regular_game_end()) { gamestate_->player_number_ = modulo(next_player_number, gamestate().board_.teams().size(), 1); } } @@ -1255,11 +1233,14 @@ void play_controller::check_time_over() if(!time_left) { LOG_NG << "firing time over event...\n"; + set_scontext_synced_base sync; pump().fire("time_over"); + LOG_NG << "done firing time over event...\n"; + // If turns are added while handling 'time over' event. - if (gamestate().tod_manager_.is_time_left()) { + if(gamestate().tod_manager_.is_time_left()) { return; } @@ -1269,9 +1250,11 @@ void play_controller::check_time_over() } check_victory(); - if (is_regular_game_end()) { + + if(is_regular_game_end()) { return; } + end_level_data e; e.proceed_to_next_level = false; e.is_victory = false; @@ -1302,8 +1285,10 @@ void play_controller::show_objectives() const void play_controller::toggle_skipping_replay() { skip_replay_ = !skip_replay_; +#if 0 const std::shared_ptr skip_animation_button = get_display().find_action_button("skip-animation"); - if (skip_animation_button) { + if(skip_animation_button) { skip_animation_button->set_check(skip_replay_); } +#endif } diff --git a/src/play_controller.hpp b/src/play_controller.hpp index 8de60f566a1c..d4d5063d12b8 100644 --- a/src/play_controller.hpp +++ b/src/play_controller.hpp @@ -1,7 +1,7 @@ /* Copyright (C) 2006 - 2018 by Joerg Hinrichs wesnoth playlevel Copyright (C) 2003 by David White - Part of the Battle for Wesnoth Project https://www.wesnoth.org/ + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -18,14 +18,13 @@ #include "controller_base.hpp" #include "floating_label.hpp" #include "game_end_exceptions.hpp" -#include "help/help.hpp" +#include "game_state.hpp" #include "hotkey/command_executor.hpp" #include "menu_events.hpp" #include "mouse_events.hpp" #include "persist_manager.hpp" #include "terrain/type_data.hpp" #include "tod_manager.hpp" -#include "game_state.hpp" #include @@ -39,49 +38,73 @@ struct mp_game_settings; class game_classification; struct unit_experience_accelerator; -namespace actions { - class undo_list; +namespace actions +{ +class undo_list; } -namespace game_events { - class manager; - class wml_event_pump; - class wml_menu_item; +namespace game_events +{ +class manager; +class wml_event_pump; +class wml_menu_item; } // namespace game_events -namespace soundsource { - class manager; +namespace soundsource +{ +class manager; } // namespace soundsource -namespace statistics { - struct scenario_context; +namespace statistics +{ +struct scenario_context; } // namespace statistics -namespace pathfind { - class manager; +namespace pathfind +{ +class manager; } -namespace tooltips { - struct manager; +namespace tooltips +{ +struct manager; } // namespace tooltips -namespace wb { - class manager; // whiteboard manager +namespace wb +{ +class manager; // whiteboard manager } // namespace wb +namespace gui2 +{ +namespace dialogs +{ +class game_ui; +} +} + // Holds gamestate related objects class game_state; class play_controller : public controller_base, public events::observer, public quit_confirmation { public: - play_controller(const config& level, saved_game& state_of_game, - const ter_data_cache& tdata, bool skip_replay); + /** Declaration for opaque pointer paradigm. */ + class hotkey_handler; + + play_controller(const config& level, + saved_game& state_of_game, + const config& game_config, + const ter_data_cache& tdata, + bool skip_replay); + virtual ~play_controller(); - //event handler, overridden from observer - //there is nothing to handle in this class actually but that might change in the future - virtual void handle_generic_event(const std::string& /*name*/) override {} + // event handler, overridden from observer + // there is nothing to handle in this class actually but that might change in the future + virtual void handle_generic_event(const std::string& /*name*/) override + { + } bool can_undo() const; bool can_redo() const; @@ -96,6 +119,7 @@ class play_controller : public controller_base, public events::observer, public void save_replay(); void save_replay_auto(const std::string& filename); void save_map(); + replay& get_replay(); void init_side_begin(); @@ -114,7 +138,6 @@ class play_controller : public controller_base, public events::observer, public virtual void force_end_turn() = 0; virtual void check_objectives() = 0; - virtual void on_not_observer() = 0; /** @@ -124,49 +147,58 @@ class play_controller : public controller_base, public events::observer, public */ virtual void process_oos(const std::string& msg) const; - void set_end_level_data(const end_level_data& data) { + void set_end_level_data(const end_level_data& data) + { gamestate().end_level_data_ = data; } - void reset_end_level_data() { + + void reset_end_level_data() + { gamestate().end_level_data_ = boost::none; } - bool is_regular_game_end() const { + + bool is_regular_game_end() const + { return gamestate().end_level_data_.get_ptr() != nullptr; } - const end_level_data& get_end_level_data_const() const { + + const end_level_data& get_end_level_data_const() const + { return *gamestate().end_level_data_; } - const std::vector& get_teams_const() const { + + const std::vector& get_teams_const() const + { return gamestate().board_.teams_; } - const unit_map& get_units_const() const { + const unit_map& get_units_const() const + { return gamestate().board_.units(); } - const gamemap& get_map_const() const{ + const gamemap& get_map_const() const + { return gamestate().board_.map(); } - const tod_manager& get_tod_manager_const() const{ - return gamestate().tod_manager_; - } - - bool is_observer() const { - return gamestate().board_.is_observer(); - } - bool do_healing() const { - return gamestate().do_healing_; + const tod_manager& get_tod_manager_const() const + { + return gamestate().tod_manager_; } - void set_do_healing(bool do_healing) { - gamestate().do_healing_ = do_healing; + bool is_observer() const + { + return gamestate().board_.is_observer(); } - game_state& gamestate() { + game_state& gamestate() + { return *gamestate_; } - const game_state& gamestate() const { + + const game_state& gamestate() const + { return *gamestate_; } @@ -177,37 +209,64 @@ class play_controller : public controller_base, public events::observer, public */ void check_victory(); - std::size_t turn() const {return gamestate().tod_manager_.turn();} + std::size_t turn() const + { + return gamestate().tod_manager_.turn(); + } /** * Returns the number of the side whose turn it is. * * Numbering starts at one. */ - int current_side() const { return gamestate_->player_number_; } + int current_side() const + { + return gamestate_->player_number_; + } /** * Builds the snapshot config from members and their respective configs. */ config to_config() const; - bool is_skipping_replay() const { return skip_replay_; } + bool is_skipping_replay() const + { + return skip_replay_; + } + void toggle_skipping_replay(); - bool is_linger_mode() const { return linger_; } - void do_autosave(); - bool is_skipping_story() const { return skip_story_; } + bool is_linger_mode() const + { + return linger_; + } + + void do_autosave(); void do_consolesave(const std::string& filename); events::mouse_handler& get_mouse_handler_base() override; - events::menu_handler& get_menu_handler() { return menu_handler_; } + + events::menu_handler& get_menu_handler() + { + return menu_handler_; + } std::shared_ptr get_whiteboard() const; + const mp_game_settings& get_mp_settings(); + game_classification& get_classification(); - int get_server_request_number() const { return gamestate().server_request_number_; } - void increase_server_request_number() { ++gamestate().server_request_number_; } + + int get_server_request_number() const + { + return gamestate().server_request_number_; + } + + void increase_server_request_number() + { + ++gamestate().server_request_number_; + } game_events::wml_event_pump& pump(); @@ -215,16 +274,24 @@ class play_controller : public controller_base, public events::observer, public virtual soundsource::manager* get_soundsource_man() override; virtual plugins_context* get_plugins_context() override; + hotkey::command_executor* get_hotkey_command_executor() override; - actions::undo_list& get_undo_stack() { return undo_stack(); } + actions::undo_list& get_undo_stack() + { + return undo_stack(); + } bool is_browsing() const override; - bool is_lingering() const { return linger_; } - - class hotkey_handler; + bool is_lingering() const + { + return linger_; + } - virtual bool is_replay() { return false; } + virtual bool is_replay() + { + return false; + } t_string get_scenario_name() const { @@ -248,12 +315,14 @@ class play_controller : public controller_base, public events::observer, public void maybe_throw_return_to_play_side() const { - if(should_return_to_play_side() && !linger_ ) { + if(should_return_to_play_side() && !linger_) { throw return_to_play_side_exception(); } } - virtual void play_side_impl() {} + virtual void play_side_impl() + { + } void play_side(); @@ -261,27 +330,45 @@ class play_controller : public controller_base, public events::observer, public const team& current_team() const; bool can_use_synced_wml_menu() const; + std::set all_players() const; - int ticks() const { return ticks_; } + + int ticks() const + { + return ticks_; + } + game_display& get_display() override; + virtual void initialize_and_show_ui() override; + void update_savegame_snapshot() const; /** * Changes the UI for this client to the passed side index. */ void update_gui_to_player(const int team_index, const bool observe = false); - virtual bool is_networked_mp() const { return false; } - virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const { } - virtual bool receive_from_wesnothd(config&) const { return false; } - /// Reevaluate [show_if] conditions and build a new objectives string. - void refresh_objectives() const; + virtual bool is_networked_mp() const + { + return false; + } + + virtual void send_to_wesnothd(const config&, const std::string& = "unknown") const + { + } + + virtual bool receive_from_wesnothd(config&) const + { + return false; + } + void show_objectives() const; struct scoped_savegame_snapshot { scoped_savegame_snapshot(const play_controller& controller); ~scoped_savegame_snapshot(); + const play_controller& controller_; }; @@ -289,28 +376,30 @@ class play_controller : public controller_base, public events::observer, public protected: friend struct scoped_savegame_snapshot; + void play_slice_catch(); - bool have_keyboard_focus() override; - void process_focus_keydown_event(const SDL_Event& event) override; + void process_keydown_event(const SDL_Event& event) override; void process_keyup_event(const SDL_Event& event) override; void init_managers(); - ///preload events cannot be synced + + /// preload events cannot be synced void fire_preload(); void fire_prestart(); void fire_start(); + void start_game(); + virtual void init_gui(); - void finish_side_turn(); - void finish_turn(); //this should not throw an end turn or end level exception - bool enemies_visible() const; - void enter_textbox(); - void tab(); + void finish_side_turn(); + void finish_turn(); // this should not throw an end turn or end level exception + bool enemies_visible() const; bool is_team_visible(int team_num, bool observer) const; + /// returns 0 if no such team was found. int find_last_visible_team() const; @@ -318,58 +407,70 @@ class play_controller : public controller_base, public events::observer, public const int ticks_; protected: - //gamestate + // gamestate const ter_data_cache& tdata_; std::unique_ptr gamestate_; config level_; saved_game& saved_game_; - //managers + // managers std::unique_ptr tooltips_manager_; - //whiteboard manager + // whiteboard manager std::shared_ptr whiteboard_manager_; - //plugins context + // plugins context std::unique_ptr plugins_context_; - //more managers + // more managers font::floating_label_context labels_manager_; - help::help_manager help_manager_; events::mouse_handler mouse_handler_; events::menu_handler menu_handler_; std::unique_ptr hotkey_handler_; std::unique_ptr soundsources_manager_; persist_manager persist_; - //other objects + // other objects std::unique_ptr gui_; + std::unique_ptr ui_; // TODO: better name? + const std::unique_ptr xp_mod_; const std::unique_ptr statistics_context_; - actions::undo_list& undo_stack() { return *gamestate().undo_stack_; } - const actions::undo_list& undo_stack() const { return *gamestate().undo_stack_; } + + actions::undo_list& undo_stack() + { + return *gamestate().undo_stack_; + } + + const actions::undo_list& undo_stack() const + { + return *gamestate().undo_stack_; + } + std::unique_ptr replay_; bool skip_replay_; - bool skip_story_; bool linger_; + /** * Whether we did init sides in this session * (false = we did init sides before we reloaded the game). */ bool init_side_done_now_; - //the displayed location when we load a game. + + // the displayed location when we load a game. map_location map_start_; + const std::string& select_music(bool victory) const; void reset_gamestate(const config& level, int replay_pos); private: - void init(const config& level); bool victory_when_enemies_defeated_; bool remove_from_carryover_on_defeat_; + std::vector victory_music_; std::vector defeat_music_; @@ -377,9 +478,16 @@ class play_controller : public controller_base, public events::observer, public protected: mutable bool ignore_replay_errors_; + bool player_type_changed_; - virtual void sync_end_turn() {} + + virtual void sync_end_turn() + { + } + virtual void check_time_over(); + virtual void update_viewing_player() = 0; + void play_turn(); };