Play Controller: formatting cleanup

This commit is contained in:
Charles Dang 2018-03-21 12:42:28 +11:00
parent fef1310890
commit a5344ae52a
2 changed files with 381 additions and 216 deletions

View file

@ -26,30 +26,30 @@
#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/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 +58,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 +86,22 @@ static lg::log_domain log_engine_enemies("engine/enemies");
static void copy_persistent(const config& src, config& dst)
{
static const std::set<std::string> attrs {
"description",
"name",
"victory_when_enemies_defeated",
"remove_from_carryover_on_defeat",
"disallow_recall",
"experience_modifier",
"require_scenario"};
"description",
"name",
"victory_when_enemies_defeated",
"remove_from_carryover_on_defeat",
"disallow_recall",
"experience_modifier",
"require_scenario"
};
static const std::set<std::string> tags {
"terrain_graphics",
"lua"};
static const std::set<std::string> tags{"terrain_graphics", "lua"};
for (const std::string& attr : attrs)
{
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,8 +124,11 @@ static void clear_resources()
resources::classification = nullptr;
}
play_controller::play_controller(const config& level, saved_game& state_of_game,
const config& game_config, const ter_data_cache& tdata, bool skip_replay)
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()
@ -169,7 +168,6 @@ 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();
@ -177,11 +175,13 @@ play_controller::play_controller(const config& level, saved_game& state_of_game,
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;
}
@ -219,6 +219,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;
@ -236,22 +237,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));
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!
@ -260,15 +266,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);
}
}
@ -276,17 +279,21 @@ 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();
gui_->initialize_ui();
}
@ -304,9 +311,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_;
@ -324,7 +331,9 @@ void play_controller::reset_gamestate(const config& level, int replay_pos)
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);
}
@ -356,11 +365,12 @@ 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") = int(turn());
}
@ -369,15 +379,17 @@ void play_controller::fire_start()
{
gamestate().gamedata_.set_phase(game_data::START);
pump().fire("start");
// start event may modify start turn with WML, reflect any changes.
gamestate().gamedata_.get_variable("turn_number") = int(turn());
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);
}
@ -393,9 +405,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);
}
@ -411,18 +422,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;
@ -436,6 +448,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;
@ -447,8 +460,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();
@ -463,15 +475,14 @@ 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);
}
@ -489,6 +500,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();
@ -498,12 +510,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() && 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();
}
@ -517,7 +531,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);
@ -530,11 +544,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());
@ -542,9 +557,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();
@ -560,20 +576,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;
}
}
@ -661,9 +680,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:
@ -676,8 +695,7 @@ 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();
}
}
@ -724,7 +742,7 @@ game_display& play_controller::get_display()
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);
}
}
@ -734,8 +752,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);
@ -746,25 +763,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();
}
@ -781,7 +797,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);
}
}
@ -803,7 +819,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);
}
}
@ -822,7 +838,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);
}
}
@ -857,8 +873,12 @@ bool play_controller::can_redo() const
const std::string& play_controller::select_music(bool victory) const
{
const std::vector<std::string>& 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.
@ -866,31 +886,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<unsigned> not_defeated;
gamestate().board_.check_victory(continue_level, found_player, found_network_player, invalidate_all, not_defeated, remove_from_carryover_on_defeat_);
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;
}
}
@ -899,24 +927,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;
@ -925,10 +959,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?");
@ -961,7 +998,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());
}
@ -995,6 +1032,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();
}
@ -1004,12 +1042,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());
}
}
@ -1018,8 +1054,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();
@ -1028,11 +1063,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);
}
@ -1040,21 +1076,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();
@ -1064,18 +1100,19 @@ 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<std::string> play_controller::all_players() const
{
std::set<std::string> 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;
}
@ -1090,6 +1127,7 @@ void play_controller::play_side()
return;
}
}
// This flag can be set by derived classes (in overridden functions).
player_type_changed_ = false;
@ -1101,9 +1139,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();
}
@ -1122,15 +1160,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_ <= int(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();
@ -1138,29 +1176,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 * 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;
@ -1169,7 +1212,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);
}
}
@ -1180,11 +1223,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;
}
@ -1194,9 +1240,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;
@ -1228,7 +1276,7 @@ void play_controller::toggle_skipping_replay()
{
skip_replay_ = !skip_replay_;
const std::shared_ptr<gui::button> 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_);
}
}

View file

@ -18,6 +18,7 @@
#include "controller_base.hpp"
#include "floating_label.hpp"
#include "game_end_exceptions.hpp"
#include "game_state.hpp"
#include "help/help.hpp"
#include "hotkey/command_executor.hpp"
#include "menu_events.hpp"
@ -25,7 +26,6 @@
#include "persist_manager.hpp"
#include "terrain/type_data.hpp"
#include "tod_manager.hpp"
#include "game_state.hpp"
#include <set>
@ -39,34 +39,41 @@ 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
// Holds gamestate related objects
@ -75,14 +82,22 @@ 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 config& game_config,
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;
@ -97,6 +112,7 @@ public:
void save_replay();
void save_replay_auto(const std::string& filename);
void save_map();
replay& get_replay();
void init_side_begin();
@ -115,7 +131,6 @@ public:
virtual void force_end_turn() = 0;
virtual void check_objectives() = 0;
virtual void on_not_observer() = 0;
/**
@ -125,41 +140,58 @@ 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<team>& get_teams_const() const {
const std::vector<team>& 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 {
const tod_manager& get_tod_manager_const() const
{
return gamestate().tod_manager_;
}
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_;
}
@ -170,35 +202,64 @@ 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_; }
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<wb::manager> 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();
@ -206,16 +267,24 @@ 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_; }
bool is_lingering() const
{
return linger_;
}
class hotkey_handler;
virtual bool is_replay() { return false; }
virtual bool is_replay()
{
return false;
}
t_string get_scenario_name() const
{
@ -239,12 +308,14 @@ 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();
@ -252,8 +323,14 @@ public:
const team& current_team() const;
bool can_use_synced_wml_menu() const;
std::set<std::string> all_players() const;
int ticks() const { return ticks_; }
int ticks() const
{
return ticks_;
}
game_display& get_display() override;
void update_savegame_snapshot() const;
@ -262,35 +339,56 @@ public:
*/
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; }
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;
protected:
struct scoped_savegame_snapshot
{
scoped_savegame_snapshot(const play_controller& controller);
~scoped_savegame_snapshot();
const play_controller& controller_;
};
friend struct scoped_savegame_snapshot;
void play_slice_catch();
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
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;
@ -298,22 +396,22 @@ private:
const int ticks_;
protected:
//gamestate
// gamestate
const ter_data_cache& tdata_;
std::unique_ptr<game_state> gamestate_;
config level_;
saved_game& saved_game_;
//managers
// managers
std::unique_ptr<tooltips::manager> tooltips_manager_;
//whiteboard manager
// whiteboard manager
std::shared_ptr<wb::manager> whiteboard_manager_;
//plugins context
// plugins context
std::unique_ptr<plugins_context> plugins_context_;
//more managers
// more managers
font::floating_label_context labels_manager_;
help::help_manager help_manager_;
events::mouse_handler mouse_handler_;
@ -322,33 +420,45 @@ protected:
std::unique_ptr<soundsource::manager> soundsources_manager_;
persist_manager persist_;
//other objects
// other objects
std::unique_ptr<game_display> gui_;
const std::unique_ptr<unit_experience_accelerator> xp_mod_;
const std::unique_ptr<const statistics::scenario_context> 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> replay_;
bool skip_replay_;
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<std::string> victory_music_;
std::vector<std::string> defeat_music_;
@ -356,9 +466,16 @@ private:
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();
};