Exemple #1
0
void holder::modify_ai(const config &cfg)
{
	if (!this->ai_) {
		// if not initialized, initialize now.
		get_ai_ref();
	}
	const std::string &act = cfg["action"];
	LOG_AI_MOD << "side "<< side_ << "        [modify_ai] "<<act<<" \""<<cfg["path"]<<"\""<<std::endl;
	DBG_AI_MOD << std::endl << cfg << std::endl;
	DBG_AI_MOD << "side "<< side_ << " before [modify_ai]"<<std::endl << to_config() << std::endl;
	bool res = false;
	if (act == "add") {
		res = component_manager::add_component(&*this->ai_,cfg["path"],cfg);
	} else if (act == "change") {
		res = component_manager::change_component(&*this->ai_,cfg["path"],cfg);
	} else if (act == "delete") {
		res = component_manager::delete_component(&*this->ai_,cfg["path"]);
	} else if (act == "try_delete") {
		res = component_manager::delete_component(&*this->ai_,cfg["path"]);
		if (!res) {
			LOG_AI_MOD << "[modify_ai] "<<act<<" failed, ignoring because it's a try_delete"<< std::endl;
			res = true;
		}
	} else {
		ERR_AI_MOD << "modify_ai tag has invalid 'action' attribute " << act << std::endl;
	}
	DBG_AI_MOD << "side "<< side_ << "  after [modify_ai]"<<act<<std::endl << to_config() << std::endl;
	if (!res) {
		LOG_AI_MOD << "[modify_ai] "<<act<<" failed"<< std::endl;
	} else {
		LOG_AI_MOD << "[modify_ai] "<<act<<" success"<< std::endl;
	}

}
Exemple #2
0
void playmp_controller::process_oos(const std::string& err_msg) const {
	// Notify the server of the oos error.
	config cfg;
	config& info = cfg.add_child("info");
	info["type"] = "termination";
	info["condition"] = "out of sync";
	network::send_data(cfg, 0);

	std::stringstream temp_buf;
	std::vector<std::string> err_lines = utils::split(err_msg,'\n');
	temp_buf << _("The game is out of sync, and cannot continue. There are a number of reasons this could happen: this can occur if you or another player have modified their game settings. This may mean one of the players is attempting to cheat. It could also be due to a bug in the game, but this is less likely.\n\nDo you want to save an error log of your game?");
	if(!err_msg.empty()) {
		temp_buf << " \n \n"; //and now the "Details:"
		for(std::vector<std::string>::iterator i=err_lines.begin(); i!=err_lines.end(); ++i)
		{
			temp_buf << "`#" << *i << '\n';
		}
		temp_buf << " \n";
	}

	config snapshot;
	to_config(snapshot);
	savegame::oos_savegame save(heros_, snapshot);
	save.save_game_interactive(resources::screen->video(), temp_buf.str(), gui::YES_NO);
}
void playsingle_controller::before_human_turn(bool save)
{
	browse_ = false;
	linger_ = false;

	gui_->refresh_access_troops(player_number_ - 1);
	gui_->refresh_access_heros(player_number_ - 1);
	ai::manager::raise_turn_started();

	if (save) {
		// uint32_t start = SDL_GetTicks();
		config snapshot;
		to_config(snapshot);
		// uint32_t mid1 = SDL_GetTicks();
		// posix_print("(mid1)used time: %u ms\n", mid1 - start);
		savegame::autosave_savegame save(heros_, heros_start_, gamestate_, *gui_, snapshot);
		// uint32_t mid2 = SDL_GetTicks();
		// posix_print("(mid2)used time: %u ms\n", mid2 - mid1);
		save.autosave(game_config::disable_autosave, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES);
		// uint32_t mid3 = SDL_GetTicks();
		// posix_print("(mid3)used time: %u ms\n", mid3 - mid2);
	} else {
		teams_[player_number_ - 1].refresh_tactic_slots(*gui_);
	}

	if (preferences::turn_bell()) {
		sound::play_bell(game_config::sounds::turn_bell);
	}
	// button: undo
	undo_stack_.clear();
	if (teams_[player_number_-1].uses_shroud() || teams_[player_number_-1].uses_fog()) {
		gui_->hide_menu("undo", true);
	} else {
		gui_->hide_menu("undo", false);
		gui_->enable_menu("undo", false);
	}
	// button: endturn
	gui_->enable_menu("play_card", true);
	gui_->enable_menu("endturn", true);
/*
	if (rpg::stratum == hero_stratum_leader) {
		if (card_mode_) {
			execute_card_uh(turn(), player_number_);
		}
		execute_guard_attack(player_number_);
	}
*/	
	// card
	refresh_card_button(current_team(), *gui_);
	// if (!network::nconnections()) {
	//	show_context_menu(NULL, *gui_);
	// } else {
		// Multiplayer mod, there is context-button when network player playing.
		// In order to display correct, need hide "before" button.
		gui_->goto_main_context_menu();
	// }
}
Exemple #4
0
void replay_controller::process_oos(const std::string& msg) const
{
	if (game_config::ignore_replay_errors) return;

	std::stringstream message;
	message << _("The replay is corrupt/out of sync. It might not make much sense to continue. Do you want to save the game?");
	message << "\n\n" << _("Error details:") << "\n\n" << msg;

	savegame::oos_savegame save(to_config());
	save.save_game_interactive(resources::screen->video(), message.str(), gui::YES_NO); // can throw end_level_exception
}
possible_end_play_signal playsingle_controller::play_scenario_init(end_level_data & /*eld*/, bool & past_prestart) {
    // At the beginning of the scenario, save a snapshot as replay_start
    if(saved_game_.replay_start().empty()) {
        saved_game_.replay_start() = to_config();
    }
    HANDLE_END_PLAY_SIGNAL( fire_preload() );

    replaying_ = (recorder.at_end() == false);

    if(!loading_game_ )
    {
        if(replaying_)
        {
            //can this codepath be reached ?
            //note this when we are entering an mp game and see the 'replay' of the game
            //this path is not reached because we receive the replay later
            config* pstart = recorder.get_next_action();
            assert(pstart->has_child("start"));
        }
        else
        {
            assert(recorder.empty());
            recorder.add_start();
            recorder.get_next_action();
        }
        //we can only use a set_scontext_synced with a non empty recorder.
        set_scontext_synced sync;

        HANDLE_END_PLAY_SIGNAL( fire_prestart() );
        init_gui();
        past_prestart = true;
        LOG_NG << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n";

        events::raise_draw_event();
        HANDLE_END_PLAY_SIGNAL( fire_start(true) );
        gui_->recalculate_minimap();
    }
    else
    {
        init_gui();
        past_prestart = true;
        events::raise_draw_event();
        HANDLE_END_PLAY_SIGNAL( fire_start(false) );
        gui_->recalculate_minimap();
    }
    return boost::none;
}
void playsingle_controller::play_scenario_init(const config& level) {
	// At the beginning of the scenario, save a snapshot as replay_start
	if(saved_game_.replay_start().empty()){
		saved_game_.replay_start() = to_config();
	}
	start_game(level);
	if( saved_game_.classification().random_mode != "" && (network::nconnections() != 0)) {
		// This won't cause errors later but we should notify the user about it in case he didn't knew it.
		gui2::show_transient_message(
			gui_->video(),
			// TODO: find a better title
			_("Game Error"),
			_("This multiplayer game uses an alternative random mode, if you don't know what this message means, then most likely someone is cheating or someone reloaded a corrupt game.")
		);
	}
	return;
}
Exemple #7
0
void playsingle_controller::before_human_turn(bool save)
{
	log_scope("player turn");
	browse_ = false;
	linger_ = false;

	ai::manager::raise_turn_started();

	if(save && level_result_ == NONE) {
		savegame::autosave_savegame save(gamestate_, *gui_, to_config(), preferences::save_compression_format());
		save.autosave(game_config::disable_autosave, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES);
	}

	if(preferences::turn_bell() && level_result_ == NONE) {
		sound::play_bell(game_config::sounds::turn_bell);
	}
}
possible_end_play_signal playsingle_controller::before_human_turn()
{
    log_scope("player turn");
    browse_ = false;
    linger_ = false;

    HANDLE_END_PLAY_SIGNAL( ai::manager::raise_turn_started() ); //This line throws exception from here: https://github.com/wesnoth/wesnoth/blob/ac96a2b91b3276e20b682210617cf87d1e0d366a/src/playsingle_controller.cpp#L954

    if(do_autosaves_ && level_result_ == NONE) {
        savegame::autosave_savegame save(saved_game_, *gui_, to_config(), preferences::save_compression_format());
        save.autosave(game_config::disable_autosave, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES);
    }

    if(preferences::turn_bell() && level_result_ == NONE) {
        sound::play_bell(game_config::sounds::turn_bell);
    }
    return boost::none;
}
LEVEL_RESULT playsingle_controller::play_scenario(
	const config::const_child_itors &story,
	bool skip_replay)
{
	uint32_t start = SDL_GetTicks();
	// level_
	//   save game: [snapshort] in save file
	//   new game: [scenario] in <scenarios>.cfg

	// Start music.
	BOOST_FOREACH (const config &m, level_.child_range("music")) {
		sound::play_music_config(m);
	}
	sound::commit_music_changes();

	if(!skip_replay) {
		// show_story(*gui_, level_["name"], story);
		// gui2::show_story(*gui_, level_["name"], story);
	}
	gui_->labels().read(level_);

	// Read sound sources
	assert(soundsources_manager_ != NULL);
	BOOST_FOREACH (const config &s, level_.child_range("sound_source")) {
		soundsource::sourcespec spec(s);
		soundsources_manager_->add(spec);
	}

	uint32_t end_sound_sources = SDL_GetTicks();
	posix_print("playsingle_controller::play_scenario, sound sources, used time: %u ms\n", end_sound_sources - start);
				
	set_victory_when_enemy_no_city(level_["victory_when_enemy_no_city"].to_bool(true));
	end_level_data &end_level = get_end_level_data();
	end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage);
	end_level.carryover_add = level_["carryover_add"].to_bool();

	try {

		uint32_t end_entering_try = SDL_GetTicks();
		posix_print("playsingle_controller::play_scenario, entering try, used time: %u ms\n", end_entering_try - end_sound_sources);
		
		fire_prestart(!loading_game_);
		uint32_t end_fire_prestart = SDL_GetTicks();
		posix_print("playsingle_controller::play_scenario, fire_prestrt, used time: %u ms\n", end_fire_prestart - end_entering_try);
		
		init_gui();

		fire_start(!loading_game_);
		gui_->recalculate_minimap();

		// replaying_ = (recorder.at_end() == false);

		// Initialize countdown clock.
		std::vector<team>::iterator t;
		for(t = teams_.begin(); t != teams_.end(); ++t) {
			if (gamestate_.mp_settings().mp_countdown && !loading_game_ ){
				t->set_countdown_time(1000 * gamestate_.mp_settings().mp_countdown_init_time);
			}
		}

		// if we loaded a save file in linger mode, skip to it.
		if (linger_) {
			//determine the bonus gold handling for this scenario
			const config end_cfg = level_.child_or_empty("endlevel");
			end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage);
			end_level.carryover_add = level_["carr`yover_add"].to_bool();
			end_level.gold_bonus = end_cfg["bonus"].to_bool(true);
			end_level.carryover_report = false;
			throw end_level_exception(SKIP_TO_LINGER);
		}

		// Avoid autosaving after loading, but still
		// allow the first turn to have an autosave.
		bool save = !loading_game_;
		for(; ; first_player_ = 1) {
			play_turn(save);
			save = true;
		} //end for loop

	} catch(game::load_game_exception& lge) {
		// Loading a new game is effectively a quit.
		//
		if (lge.game != "") {
			gamestate_ = game_state();
		}
		throw lge;
	} catch (end_level_exception &end_level_exn) {
		LEVEL_RESULT end_level_result = end_level_exn.result;
		if (!end_level.custom_endlevel_music.empty()) {
			if (end_level_result == DEFEAT) {
				set_defeat_music_list(end_level.custom_endlevel_music);
			} else {
				set_victory_music_list(end_level.custom_endlevel_music);
			}
		}

		if (teams_.empty())
		{
			//store persistent teams
			gamestate_.snapshot = config();

			return VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event
		}
		const bool obs = is_observer();
		if (end_level_result == DEFEAT || end_level_result == VICTORY)
		{
			gamestate_.classification().completion = (end_level_exn.result == VICTORY) ? "victory" : "defeat";
			// If we're a player, and the result is victory/defeat, then send
			// a message to notify the server of the reason for the game ending.
			if (!obs) {
				config cfg;
				config& info = cfg.add_child("info");
				info["type"] = "termination";
				info["condition"] = "game over";
				info["result"] = gamestate_.classification().completion;
				network::send_data(cfg, 0);
			} else {
				gui2::show_transient_message(gui_->video(),_("Game Over"),
									_("The game is over."));
				return OBSERVER_END;
			}
		}

		if (end_level_result == QUIT) {
			return QUIT;
		}
		else if (end_level_result == DEFEAT)
		{
			gamestate_.classification().completion = "defeat";
			game_events::fire("defeat");

			if (!obs) {
				const std::string& defeat_music = select_defeat_music();
				if(defeat_music.empty() != true)
					sound::play_music_once(defeat_music);

				return DEFEAT;
			} else {
				return QUIT;
			}
		}
		else if (end_level_result == VICTORY)
		{
			gamestate_.classification().completion =
				!end_level.linger_mode ? "running" : "victory";
			game_events::fire("victory");

			//
			// Play victory music once all victory events
			// are finished, if we aren't observers.
			//
			// Some scenario authors may use 'continue'
			// result for something that is not story-wise
			// a victory, so let them use [music] tags
			// instead should they want special music.
			//
			if (!obs && end_level.linger_mode) {
				const std::string& victory_music = select_victory_music();
				if(victory_music.empty() != true)
					sound::play_music_once(victory_music);
			}

			// Add all the units that survived the scenario.
			LOG_NG << "Add units that survived the scenario to the recall list.\n";
			//store all units that survived (recall list for the next scenario) in snapshot
			gamestate_.snapshot = config();
			//store gold and report victory
			store_gold(obs);
			return VICTORY;
		}
		else if (end_level_result == SKIP_TO_LINGER)
		{
			LOG_NG << "resuming from loaded linger state...\n";
			//as carryover information is stored in the snapshot, we have to re-store it after loading a linger state
			gamestate_.snapshot = config();
			store_gold();
			return VICTORY;
		}
	} // end catch
	catch(network::error& e) {
		bool disconnect = false;
		if(e.socket) {
			e.disconnect();
			disconnect = true;
		}

		config snapshot;
		to_config(snapshot);
		savegame::game_savegame save(heros_, heros_start_, gamestate_, *gui_, snapshot);
		save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO);
		if(disconnect) {
			throw network::error();
		} else {
			return QUIT;
		}
	}

	return QUIT;
}
LEVEL_RESULT playsingle_controller::play_scenario(
	const config::const_child_itors &story,
	bool skip_replay)
{
	LOG_NG << "in playsingle_controller::play_scenario()...\n";

	// Start music.
	foreach (const config &m, level_.child_range("music")) {
		sound::play_music_config(m);
	}
	sound::commit_music_changes();

	if(!skip_replay) {
		show_story(*gui_, level_["name"], story);
	}
	gui_->labels().read(level_);

	// Read sound sources
	assert(soundsources_manager_ != NULL);
	foreach (const config &s, level_.child_range("sound_source")) {
		soundsource::sourcespec spec(s);
		soundsources_manager_->add(spec);
	}

	set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true));
	end_level_data &end_level = get_end_level_data();
	end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage);
	end_level.carryover_add = level_["carryover_add"].to_bool();

	bool past_prestart = false;

	LOG_NG << "entering try... " << (SDL_GetTicks() - ticks_) << "\n";
	try {

		fire_prestart(!loading_game_);
		init_gui();

		past_prestart = true;

		LOG_NG << "first_time..." << (recorder.is_skipping() ? "skipping" : "no skip") << "\n";

		events::raise_draw_event();
		fire_start(!loading_game_);
		gui_->recalculate_minimap();

		replaying_ = (recorder.at_end() == false);

		LOG_NG << "starting main loop\n" << (SDL_GetTicks() - ticks_) << "\n";

		// Initialize countdown clock.
		std::vector<team>::iterator t;
		for(t = teams_.begin(); t != teams_.end(); ++t) {
			if (gamestate_.mp_settings().mp_countdown && !loading_game_ ){
				t->set_countdown_time(1000 * gamestate_.mp_settings().mp_countdown_init_time);
			}
		}

		// if we loaded a save file in linger mode, skip to it.
		if (linger_) {
			//determine the bonus gold handling for this scenario
			end_level.read(level_.child_or_empty("endlevel"));
			end_level.carryover_report = false;
			end_level.disabled = true;
			throw end_level_exception(SKIP_TO_LINGER);
		}

		// Avoid autosaving after loading, but still
		// allow the first turn to have an autosave.
		bool save = !loading_game_;
		ai_testing::log_game_start();
		for(; ; first_player_ = 1) {
			play_turn(save);
			save = true;
		} //end for loop

#ifdef _MSC_VER
//MSVC claims that const game::load_game_exception& lge would be unreferenced...
#pragma warning (push)
#pragma warning (disable : 4101)
#endif
	} catch(const game::load_game_exception& lge) {
		// Loading a new game is effectively a quit.
		//
		if (lge.game != "") {
			gamestate_ = game_state();
		}
		throw;
	} catch (end_level_exception &end_level_exn) {
		if(!past_prestart) {
			draw_solid_tinted_rectangle(
				0, 0, gui_->video().getx(), gui_->video().gety(), 0, 0, 0, 1.0,
				gui_->video().getSurface()
			);
			update_rect(0, 0, gui_->video().getx(), gui_->video().gety());
		}

		ai_testing::log_game_end();
		LEVEL_RESULT end_level_result = end_level_exn.result;
		if (!end_level.custom_endlevel_music.empty()) {
			if (end_level_result == DEFEAT) {
				set_defeat_music_list(end_level.custom_endlevel_music);
			} else {
				set_victory_music_list(end_level.custom_endlevel_music);
			}
		}

		if (teams_.empty())
		{
			//store persistent teams
			gamestate_.snapshot = config();
			store_recalls();

			return VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event
		}
		const bool obs = is_observer();
		if (game_config::exit_at_end) {
			exit(0);
		}
		if (end_level_result == DEFEAT || end_level_result == VICTORY)
		{
			gamestate_.classification().completion = (end_level_exn.result == VICTORY) ? "victory" : "defeat";
			// If we're a player, and the result is victory/defeat, then send
			// a message to notify the server of the reason for the game ending.
			if (!obs) {
				config cfg;
				config& info = cfg.add_child("info");
				info["type"] = "termination";
				info["condition"] = "game over";
				info["result"] = gamestate_.classification().completion;
				network::send_data(cfg, 0);
			} else {
				gui2::show_transient_message(gui_->video(),_("Game Over"),
									_("The game is over."));
				return OBSERVER_END;
			}
		}

		if (end_level_result == QUIT) {
			return QUIT;
		}
		else if (end_level_result == DEFEAT)
		{
			gamestate_.classification().completion = "defeat";
			game_events::fire("defeat");

			if (!obs) {
				const std::string& defeat_music = select_defeat_music();
				if(defeat_music.empty() != true)
					sound::play_music_once(defeat_music);

				return DEFEAT;
			} else {
				return QUIT;
			}
		}
		else if (end_level_result == VICTORY)
		{
			gamestate_.classification().completion =
				!end_level.linger_mode ? "running" : "victory";
			game_events::fire("victory");

			//
			// Play victory music once all victory events
			// are finished, if we aren't observers.
			//
			// Some scenario authors may use 'continue'
			// result for something that is not story-wise
			// a victory, so let them use [music] tags
			// instead should they want special music.
			//
			if (!obs && end_level.linger_mode) {
				const std::string& victory_music = select_victory_music();
				if(victory_music.empty() != true)
					sound::play_music_once(victory_music);
			}

			// Add all the units that survived the scenario.
			LOG_NG << "Add units that survived the scenario to the recall list.\n";
			for(unit_map::iterator un = units_.begin(); un != units_.end(); ++un) {

				if (teams_[un->side() - 1].persistent()) {
					LOG_NG << "Added unit " << un->id() << ", " << un->name() << "\n";
					un->new_turn();
					un->new_scenario();
					teams_[un->side() - 1].recall_list().push_back(*un);
				}
			}
			//store all units that survived (recall list for the next scenario) in snapshot
			gamestate_.snapshot = config();
			store_recalls();
			//store gold and report victory
			store_gold(obs);
			return VICTORY;
		}
		else if (end_level_result == SKIP_TO_LINGER)
		{
			LOG_NG << "resuming from loaded linger state...\n";
			//as carryover information is stored in the snapshot, we have to re-store it after loading a linger state
			gamestate_.snapshot = config();
			store_recalls();
			store_gold();
			return VICTORY;
		}
	} // end catch
	catch(network::error& e) {
		bool disconnect = false;
		if(e.socket) {
			e.disconnect();
			disconnect = true;
		}

		savegame::game_savegame save(gamestate_, *gui_, to_config(), preferences::compress_saves());
		save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO);
		if(disconnect) {
			throw network::error();
		} else {
			return QUIT;
		}
	}

	return QUIT;
}
LEVEL_RESULT playsingle_controller::play_scenario(
    const config::const_child_itors &story,
    bool skip_replay)
{
    LOG_NG << "in playsingle_controller::play_scenario()...\n";

    // Start music.
    BOOST_FOREACH(const config &m, level_.child_range("music")) {
        sound::play_music_config(m);
    }
    sound::commit_music_changes();

    if(!skip_replay) {
        show_story(*gui_, level_["name"], story);
    }
    gui_->labels().read(level_);

    // Read sound sources
    assert(soundsources_manager_ != NULL);
    BOOST_FOREACH(const config &s, level_.child_range("sound_source")) {
        try {
            soundsource::sourcespec spec(s);
            soundsources_manager_->add(spec);
        } catch (bad_lexical_cast &) {
            ERR_NG << "Error when parsing sound_source config: bad lexical cast." << std::endl;
            ERR_NG << "sound_source config was: " << s.debug() << std::endl;
            ERR_NG << "Skipping this sound source..." << std::endl;
        }
    }

    set_victory_when_enemies_defeated(level_["victory_when_enemies_defeated"].to_bool(true));
    set_remove_from_carryover_on_defeat(level_["remove_from_carryover_on_defeat"].to_bool(true));
    end_level_data &end_level = get_end_level_data();
    end_level.carryover_percentage = level_["carryover_percentage"].to_int(game_config::gold_carryover_percentage);
    end_level.carryover_add = level_["carryover_add"].to_bool();

    bool past_prestart = false;

    LOG_NG << "entering try... " << (SDL_GetTicks() - ticks_) << "\n";
    try {
        possible_end_play_signal signal = play_scenario_init(end_level, past_prestart);

        if (!signal) {

            signal = play_scenario_main_loop(end_level, past_prestart);
        }

        if (signal) {
            switch (boost::apply_visitor( get_signal_type(), *signal )) {
            //BEGIN CASES
            case END_TURN:
                assert(false && "end turn signal propogated to playsingle_controller::play_scenario. This results in terminate!");
                throw 42;
            case END_LEVEL:
                if(!past_prestart) {
                    sdl::draw_solid_tinted_rectangle(
                        0, 0, gui_->video().getx(), gui_->video().gety(), 0, 0, 0, 1.0,
                        gui_->video().getSurface()
                    );
                    update_rect(0, 0, gui_->video().getx(), gui_->video().gety());
                }

                ai_testing::log_game_end();
                LEVEL_RESULT end_level_result = boost::apply_visitor( get_result(), *signal );
                if (!end_level.transient.custom_endlevel_music.empty()) {
                    if (end_level_result == DEFEAT) {
                        set_defeat_music_list(end_level.transient.custom_endlevel_music);
                    } else {
                        set_victory_music_list(end_level.transient.custom_endlevel_music);
                    }
                }

                if (gamestate_.board_.teams().empty())
                {
                    //store persistent teams
                    saved_game_.set_snapshot(config());

                    return VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event
                }
                const bool obs = is_observer();
                if (game_config::exit_at_end) {
                    exit(0);
                }
                if (end_level_result == DEFEAT || end_level_result == VICTORY)
                {
                    saved_game_.classification().completion = (end_level_result == VICTORY) ? "victory" : "defeat";
                    // If we're a player, and the result is victory/defeat, then send
                    // a message to notify the server of the reason for the game ending.
                    if (!obs) {
                        config cfg;
                        config& info = cfg.add_child("info");
                        info["type"] = "termination";
                        info["condition"] = "game over";
                        info["result"] = saved_game_.classification().completion;
                        network::send_data(cfg, 0);
                    } else {
                        gui2::show_transient_message(gui_->video(),_("Game Over"),
                                                     _("The game is over."));
                        return OBSERVER_END;
                    }
                }

                if (end_level_result == QUIT) {
                    return QUIT;
                }
                else if (end_level_result == DEFEAT)
                {
                    saved_game_.classification().completion = "defeat";
                    game_events::fire("defeat");

                    if (!obs) {
                        const std::string& defeat_music = select_defeat_music();
                        if(defeat_music.empty() != true)
                            sound::play_music_once(defeat_music);

                        persist_.end_transaction();
                        return DEFEAT;
                    } else {
                        return QUIT;
                    }
                }
                else if (end_level_result == VICTORY)
                {
                    saved_game_.classification().completion =
                        !end_level.transient.linger_mode ? "running" : "victory";
                    game_events::fire("victory");

                    //
                    // Play victory music once all victory events
                    // are finished, if we aren't observers.
                    //
                    // Some scenario authors may use 'continue'
                    // result for something that is not story-wise
                    // a victory, so let them use [music] tags
                    // instead should they want special music.
                    //
                    if (!obs && end_level.transient.linger_mode) {
                        const std::string& victory_music = select_victory_music();
                        if(victory_music.empty() != true)
                            sound::play_music_once(victory_music);
                    }

                    // Add all the units that survived the scenario.
                    // this function doesn't move unit to the recalllist anymore i just keep this name to prevent merging conflicts.
                    LOG_NG << "Add units that survived the scenario to the recall list.\n";
                    gamestate_.board_.all_survivors_to_recall();

                    saved_game_.remove_snapshot();
                    if(!is_observer()) {
                        persist_.end_transaction();
                    }

                    return VICTORY;
                }
                else if (end_level_result == SKIP_TO_LINGER)
                {
                    LOG_NG << "resuming from loaded linger state...\n";
                    //as carryover information is stored in the snapshot, we have to re-store it after loading a linger state
                    saved_game_.set_snapshot(config());
                    if(!is_observer()) {
                        persist_.end_transaction();
                    }
                    return VICTORY;
                }

                break;
                //END CASES
            } // END SWITCH
        } //end if
    } catch(const game::load_game_exception &) {
        // Loading a new game is effectively a quit.
        //
        if ( game::load_game_exception::game != "" ) {
            saved_game_ = saved_game();
        }
        throw;
    } catch(network::error& e) {
        bool disconnect = false;
        if(e.socket) {
            e.disconnect();
            disconnect = true;
        }

        savegame::ingame_savegame save(saved_game_, *gui_, to_config(), preferences::save_compression_format());
        save.save_game_interactive(gui_->video(), _("A network disconnection has occurred, and the game cannot continue. Do you want to save the game?"), gui::YES_NO);
        if(disconnect) {
            throw network::error();
        } else {
            return QUIT;
        }
    }

    return QUIT;
}
Exemple #12
0
void play_controller::update_savegame_snapshot() const
{
    //note: this writes to level_ if this is not a replay.
    this->saved_game_.set_snapshot(to_config());
}
void playsingle_controller::before_human_turn(bool save)
{
	team& t = current_team();

	if (pause_when_human_) {
		browse_ = false;
	}
	linger_ = false;

	if (gui_->access_is_null(game_display::taccess_list::TROOP)) {
		// change resolution will result to enter it.
		gui_->refresh_access_troops(player_number_ - 1, game_display::REFRESH_RELOAD);
	}
	if (!tent::tower_mode() && !preferences::developer()) {
		gui_->refresh_access_troops(player_number_ - 1, game_display::REFRESH_HIDE, NULL);
	}
	gui_->refresh_access_heros(player_number_ - 1, game_display::REFRESH_RELOAD);
	ai::manager::raise_turn_started();

	if (tent::mode != mode_tag::LAYOUT && save) {
		autosave_ticks_ = unit_map::main_ticks;

		config snapshot;
		to_config(snapshot);
		savegame::autosave_savegame save(heros_, heros_start_, gamestate_, *gui_, snapshot);
		save.autosave(game_config::disable_autosave, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES);

		if (tent::turn_based) {
			const std::vector<hero*>& last_active_tactic = t.last_active_tactic();
			for (std::vector<hero*>::const_iterator it = last_active_tactic.begin(); it != last_active_tactic.end(); ++ it) {
				hero& selected_hero = **it;
				unit* tactician = units_.find_unit(selected_hero);
				if (tactician && !tactician->is_resided()) {
					do_add_active_tactic(*tactician, selected_hero, true);
				}
			}
		}

		// autosave ticks changed, refresh top panel.
		gui_->invalidate_game_status();

	} else {
		teams_[player_number_ - 1].refresh_tactic_slots(*gui_);
	}

	if (unit::actor && unit::actor->is_city()) {
		if (preferences::turn_bell()) {
			sound::play_bell(game_config::sounds::turn_bell);
		}
		if (game_config::show_side_report) {
			gui2::tside_report dlg(*gui_, teams_, units_, heros_, unit::actor->side());
			dlg.show(gui_->video());
		}
	}

	// button: undo
	undo_stack_.clear();
	if (teams_[player_number_-1].uses_shroud() || teams_[player_number_-1].uses_fog()) {
		gui_->set_theme_object_visible("undo", gui2::twidget::INVISIBLE);
	} else {
		gui_->set_theme_object_visible("undo", gui2::twidget::VISIBLE);
		gui_->set_theme_object_active("undo", false);
	}
	// button: endturn
	if (tent::mode == mode_tag::SIEGE) {
		if (pause_when_human_) {
			refresh_endturn_button(*gui_, "buttons/ctrl-play.png");
			gui_->set_theme_object_active("endturn", true);
		}
		
	} else if (tent::mode != mode_tag::LAYOUT) {
		gui_->set_theme_object_active("card", true);
		gui_->set_theme_object_active("endturn", true);
	} else {
		gui_->set_theme_object_visible("card", gui2::twidget::INVISIBLE);
		gui_->set_theme_object_visible("endturn", gui2::twidget::INVISIBLE);
	}
	
	// card
	refresh_card_button(t, *gui_);
	// if (!network::nconnections()) {
	//	gui_->show_context_menu();
	// } else {
		// Multiplayer mod, there is context-button when network player playing.
		// In order to display correct, need hide "before" button.
		gui_->goto_main_context_menu();
	// }
}