void synced_context::server_choice::send_request() const { resources::controller->send_to_wesnothd(config_of ("request_choice", config_of ("request_id", resources::controller->get_server_request_number()) (name(), request()) ) ); }
void tchatbox::send_chat_message(const std::string& message, bool /*allies_only*/) { ::config c = config_of("message", config_of("message", message)("sender", preferences::login())); add_chat_message(time(nullptr), preferences::login(), 0, message); if(wesnothd_connection_) { wesnothd_connection_->send_data(c); } }
void tod_manager::update_server_information() const { if(resources::controller->current_team().is_local()) { //the currently active side informs the mp server about the turn change. //NOTE: The current implementation does not guarnateee that the server gets informed // about those changes in 100% of cases. But that is ok because the information is only // used to display the turn limit in the lobby (as opposed to things that cause OOS). resources::controller->send_to_wesnothd(config_of ("change_turns_wml", config_of ("current", turn_) ("max", num_turns_) ) ); } }
void playturn_network_adapter::read_from_network() { assert(!data_.empty()); this->data_.push_back(config()); config& back = data_.back(); bool has_data = this->network_reader_(back); //ping is handeled by network.cpp and we can ignore it. back.remove_attribute("ping"); if((!has_data) || back.empty()) { this->data_.pop_back(); return; } assert(!data_.back().empty()); if(back.has_attribute("side_drop")) { config child; child["side_num"] = back["side_drop"]; child["controller"] = back["controller"]; this->data_.push_back(config_of("side_drop", child)); back.remove_attribute("side_drop"); back.remove_attribute("controller"); } assert(!data_.back().empty()); //there should be no attributes left. if(back.attribute_range().first != back.attribute_range().second ) { ERR_NW << "found unexpected attribute:" <<back.debug() << "\n"; } }
void mp_staging::network_handler(window& window) { // First, send off any changes if they've been accumulated if(state_changed_) { connect_engine_.update_and_send_diff(); } // Next, check for any incoming changes config data; if(!state_changed_ && (!wesnothd_connection_ || !wesnothd_connection_->receive_data(data))) { return; } // Update chat find_widget<chatbox>(&window, "chat", false).process_network_data(data); // TODO: why is this needed... const bool was_able_to_start = connect_engine_.can_start_game(); bool quit_signal_recieved; std::tie(quit_signal_recieved, std::ignore) = connect_engine_.process_network_data(data); if(quit_signal_recieved) { window.set_retval(window::CANCEL); } // Update side leader displays // This is basically only needed when a new player joins and selects their faction for(auto& tree_entry : side_tree_map_) { ng::side_engine_ptr side = tree_entry.first; grid& row_grid = tree_entry.second->get_grid(); update_leader_display(side, row_grid); std::vector<config> controller_names; for(const auto& controller : side->controller_options()) { controller_names.push_back(config_of("label", controller.second)); } menu_button& controller_selection = find_widget<menu_button>(&row_grid, "controller", false); controller_selection.set_values(controller_names, side->current_controller_index()); controller_selection.set_active(controller_names.size() > 1); } // Update player list // TODO: optimally, it wouldn't regenerate the entire list every single refresh cycle update_player_list(window); // Update status label and buttons update_status_label_and_buttons(window); if(!was_able_to_start && connect_engine_.can_start_game()) { mp_ui_alerts::ready_for_start(); } state_changed_ = false; }
static config find_helper(const ng::create_engine * eng_ptr, const config & cfg) { assert(eng_ptr); const ng::create_engine & eng = *eng_ptr; std::string str = cfg["id"].str(); return config_of("index", eng.find_level_by_id(str))("type", eng.find_level_type_by_id(str)); }
void create_engine::prepare_for_scenario() { DBG_MP << "preparing data for scenario by reloading game config\n"; state_.classification().scenario_define = current_level().data()["define"].str(); state_.set_carryover_sides_start( config_of("next_scenario", current_level().data()["id"]) ); }
cave_map_generator::cave_map_generator_job::cave_map_generator_job(const cave_map_generator& pparams, boost::optional<uint32_t> randomseed) : params(pparams) , flipx_(false) , flipy_(false) , map_(t_translation::ter_map(params.width_ + 2 * gamemap::default_border, params.height_ + 2 * gamemap::default_border/*, params.wall_*/)) , starting_positions_() , chamber_ids_() , chambers_() , passages_() , res_(params.cfg_.child_or_empty("settings")) , rng_() //initialises with rand() { res_.add_child("event", config_of ("name", "start") ("message", config_of ("message", "scenario_generation=cave is deprecated and will be removed soon.") ) ); uint32_t seed = randomseed.get_ptr() ? *randomseed.get_ptr() : seed_rng::next_seed(); rng_.seed(seed); LOG_NG << "creating random cave with seed: " << seed << '\n'; flipx_ = int(rng_() % 100) < params.flipx_chance_; flipy_ = int(rng_() % 100) < params.flipy_chance_; LOG_NG << "creating scenario....\n"; generate_chambers(); LOG_NG << "placing chambers...\n"; for(std::vector<chamber>::const_iterator c = chambers_.begin(); c != chambers_.end(); ++c) { place_chamber(*c); } LOG_NG << "placing passages...\n"; for(std::vector<passage>::const_iterator p = passages_.begin(); p != passages_.end(); ++p) { place_passage(*p); } LOG_NG << "outputting map....\n"; res_["map_data"] = t_translation::write_game_map(map_, starting_positions_); }
void game_launcher::set_tutorial() { state_ = saved_game(); state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TUTORIAL; state_.classification().campaign_define = "TUTORIAL"; state_.mp_settings().mp_era = "era_default"; state_.mp_settings().show_connect = false; state_.set_carryover_sides_start( config_of("next_scenario", "tutorial") ); }
void playturn_network_adapter::read_from_network() { assert(!data_.empty()); this->data_.push_back(config()); config& back = data_.back(); bool has_data = false; try { has_data = this->network_reader_(back); } catch(...) { //Readin from network can throw, we want to ignore the possibly corrupt packet in this case. this->data_.pop_back(); throw; } //ping is handeled by network.cpp and we can ignore it. back.remove_attribute("ping"); if((!has_data) || back.empty()) { this->data_.pop_back(); return; } assert(!data_.back().empty()); if(back.has_attribute("side_drop")) { config child; child["side_num"] = back["side_drop"]; child["controller"] = back["controller"]; this->data_.push_back(config_of("side_drop", child)); back.remove_attribute("side_drop"); back.remove_attribute("controller"); } else if(!back.attribute_range().empty() ) { ERR_NW << "found unexpected attribute:" <<back.debug() << std::endl; this->data_.pop_back(); //ignore those here } assert(!data_.back().empty()); //there should be no attributes left. }
void play_scenario::play() { // We have to first append a "event" that collects end poisition end_pos_.reset(new end_position_collector(current_time_++)); end_position_collector* end = static_cast<end_position_collector*>(end_pos_.get()); source_.add_event(end_pos_); source_.type_key(current_time_++, SDLK_COLON, SDLMod(KMOD_LSHIFT | KMOD_SHIFT) ); source_.type_key(current_time_++, SDLK_q); source_.type_key(current_time_++, SDLK_EXCLAIM); source_.type_key(current_time_++, SDLK_RETURN); saved_game& state = end->get_state(); state.classification().campaign_type = game_classification::TEST; state.set_carryover_sides_start( config_of("next_scenario", id_) ); play_game(get_fake_display(1024, 768), state, game_config_, tdata_); }
void set_scontext_synced::do_final_checkup(bool dont_throw) { assert(!did_final_checkup_); std::stringstream msg; config co; config cn = config_of ("random_calls", new_rng_->get_random_calls()) ("next_unit_id", resources::gameboard->unit_id_manager().get_save_id() + 1); if(checkup_instance->local_checkup(cn, co)) { return; } if(co["random_calls"].empty()) { msg << "cannot find random_calls check in replay" << std::endl; } else if(co["random_calls"] != cn["random_calls"]) { msg << "We called random " << new_rng_->get_random_calls() << " times, but the original game called random " << co["random_calls"].to_int() << " times." << std::endl; } //Ignore empty next_unit_id to prevent false positives with older saves. if(!co["next_unit_id"].empty() && co["next_unit_id"] != cn["next_unit_id"]) { msg << "Our next unit id is " << cn["next_unit_id"].to_int() << " but during the original the next unit id was " << co["next_unit_id"].to_int() << std::endl; } if(!msg.str().empty()) { msg << co.debug() << std::endl; if(dont_throw) { ERR_REPLAY << msg.str() << std::flush; } else { replay::process_error(msg.str()); } } did_final_checkup_ = true; }
bool game_launcher::play_test() { static bool first_time = true; if(!cmdline_opts_.test) { return true; } if(!first_time) return false; first_time = false; state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TEST; state_.classification().campaign_define = "TEST"; state_.mp_settings().mp_era = "era_default"; state_.mp_settings().show_connect = false; state_.set_carryover_sides_start( config_of("next_scenario", test_scenario_) ); game_config_manager::get()-> load_game_config_for_game(state_.classification()); try { campaign_controller ccontroller(video(), state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types()); ccontroller.play_game(); } catch (savegame::load_game_exception &e) { load_data_.reset(new savegame::load_game_metadata(std::move(e.data_))); return true; } return false; }
void create_engine::prepare_for_campaign(const std::string& difficulty) { DBG_MP << "preparing data for campaign by reloading game config\n"; if (difficulty != "") { state_.classification().difficulty = difficulty; } state_.classification().campaign = current_level().data()["id"].str(); state_.classification().abbrev = current_level().data()["abbrev"].str(); state_.classification().end_text = current_level().data()["end_text"].str(); state_.classification().end_text_duration = current_level().data()["end_text_duration"]; state_.classification().campaign_define = current_level().data()["define"].str(); state_.classification().campaign_xtra_defines = utils::split(current_level().data()["extra_defines"]); state_.set_carryover_sides_start( config_of("next_scenario", current_level().data()["first_scenario"]) ); }
bool enter_create_mode(game_display& disp, const config& game_config, saved_game& state, jump_to_campaign_info jump_to_campaign, bool local_players_only) { bool configure_canceled = false; do { ng::create_engine create_eng(disp, state); create_eng.set_current_level_type(ng::level::TYPE::SP_CAMPAIGN); std::vector<ng::create_engine::level_ptr> campaigns( create_eng.get_levels_by_type_unfiltered(ng::level::TYPE::SP_CAMPAIGN)); if (campaigns.empty()) { gui2::show_error_message(disp.video(), _("No campaigns are available.\n")); return false; } bool use_deterministic_mode = false; // No campaign selected from command line if (jump_to_campaign.campaign_id_.empty() == true) { gui2::tcampaign_selection dlg(create_eng); try { dlg.show(disp.video()); } catch(twml_exception& e) { e.show(disp); return false; } if(dlg.get_retval() != gui2::twindow::OK) { return false; } use_deterministic_mode = dlg.get_deterministic(); } else { // don't reset the campaign_id_ so we can know // if we should quit the game or return to the main menu // checking for valid campaign name bool not_found = true; for(size_t i = 0; i < campaigns.size(); ++i) { if (campaigns[i]->data()["id"] == jump_to_campaign.campaign_id_) { create_eng.set_current_level(i); not_found = false; break; } } // didn't find any campaign with that id if (not_found) { //TODO: use ERR_NG or similar std::cerr<<"No such campaign id to jump to: ["<<jump_to_campaign.campaign_id_<<"]\n"; return false; } } std::string random_mode = use_deterministic_mode ? "deterministic" : ""; state.classification().random_mode = random_mode; std::string selected_difficulty = create_eng.select_campaign_difficulty(jump_to_campaign.difficulty_); if (selected_difficulty == "FAIL") return false; if (selected_difficulty == "CANCEL") { if (jump_to_campaign.campaign_id_.empty() == false) { jump_to_campaign.campaign_id_ = ""; } // canceled difficulty dialog, relaunch the campaign selection dialog return enter_create_mode(disp, game_config, state, jump_to_campaign, local_players_only); } create_eng.prepare_for_era_and_mods(); create_eng.prepare_for_campaign(selected_difficulty); if(!jump_to_campaign.scenario_id_.empty()) { state.set_carryover_sides_start( config_of("next_scenario", jump_to_campaign.scenario_id_) ); } create_eng.prepare_for_new_level(); create_eng.get_parameters(); if(!state.valid()) { //TODO: use ERR_NG or similar std::cerr << "Cannot load scenario with id=" << state.get_scenario_id() << "\n"; return false; } configure_canceled = !enter_configure_mode(disp, game_config_manager::get()->game_config(), state, local_players_only); } while (configure_canceled); return true; }
bool enter_create_mode(CVideo& video, const config& game_config, saved_game& state, jump_to_campaign_info jump_to_campaign, bool local_players_only) { bool configure_canceled = false; do { ng::create_engine create_eng(video, state); create_eng.set_current_level_type(ng::level::TYPE::SP_CAMPAIGN); const std::vector<ng::create_engine::level_ptr> campaigns = create_eng.get_levels_by_type_unfiltered(ng::level::TYPE::SP_CAMPAIGN); if(campaigns.empty()) { gui2::show_error_message(video, _("No campaigns are available.")); return false; } std::string random_mode = ""; // No campaign selected from command line if(jump_to_campaign.campaign_id_.empty()) { gui2::tcampaign_selection dlg(create_eng); try { dlg.show(video); } catch(twml_exception& e) { e.show(video); return false; } if(dlg.get_retval() != gui2::twindow::OK) { return false; } if(dlg.get_deterministic()) { random_mode = "deterministic"; } } else { // Don't reset the campaign_id_ so we can know // if we should quit the game or return to the main menu // Checking for valid campaign name const auto campaign = std::find_if(campaigns.begin(), campaigns.end(), [&jump_to_campaign](ng::create_engine::level_ptr level) { return level->data()["id"] == jump_to_campaign.campaign_id_; }); // Didn't find a campaign with that id if(campaign == campaigns.end()) { ERR_NG << "No such campaign id to jump to: [" << jump_to_campaign.campaign_id_ << "]" << std::endl; return false; } create_eng.set_current_level(campaign - campaigns.begin()); } state.classification().random_mode = random_mode; const std::string selected_difficulty = create_eng.select_campaign_difficulty(jump_to_campaign.difficulty_); if(selected_difficulty == "FAIL") return false; if(selected_difficulty == "CANCEL") { if(!jump_to_campaign.campaign_id_.empty()) { jump_to_campaign.campaign_id_ = ""; } // Canceled difficulty dialog, relaunch the campaign selection dialog return enter_create_mode(video, game_config, state, jump_to_campaign, local_players_only); } create_eng.prepare_for_era_and_mods(); create_eng.prepare_for_campaign(selected_difficulty); if(!jump_to_campaign.scenario_id_.empty()) { state.set_carryover_sides_start( config_of("next_scenario", jump_to_campaign.scenario_id_) ); } if(!state.valid()) { ERR_NG << "Cannot load scenario with id=" << state.get_scenario_id() << std::endl; return false; } configure_canceled = !enter_configure_mode(video, game_config_manager::get()->game_config(), state, create_eng, local_players_only); } while (configure_canceled); return true; }
void mp_staging::add_side_node(window& window, ng::side_engine_ptr side) { tree_view& tree = find_widget<tree_view>(&window, "side_list", false); static const std::map<std::string, string_map> empty_map; std::map<std::string, string_map> data; string_map item; item["label"] = std::to_string(side->index() + 1); data.emplace("side_number", item); // TODO: don't hardcode meganta? item["label"] = "units/unknown-unit.png~RC(magenta>" + std::to_string(side->color() + 1) + ")"; data.emplace("leader_image", item); item["label"] = "icons/icon-random.png"; data.emplace("leader_gender", item); // Check to see whether we've added a toplevel tree node for this team. If not, add one if(team_tree_map_.find(side->team_name()) == team_tree_map_.end()) { std::map<std::string, string_map> data; string_map item; item["label"] = (formatter() << _("Team:") << " " << side->user_team_name()).str(); data.emplace("tree_view_node_label", item); tree_view_node& team_node = tree.add_node("team_header", data); team_node.add_sibling("side_spacer", empty_map); team_tree_map_[side->team_name()] = &team_node; } tree_view_node& node = team_tree_map_[side->team_name()]->add_child("side_panel", data); side_tree_map_[side] = &node; grid& row_grid = node.get_grid(); update_leader_display(side, row_grid); // Status variables const bool fls = connect_engine_.force_lock_settings(); const bool ums = connect_engine_.params().use_map_settings; const bool lock_gold = side->cfg()["gold_lock"].to_bool(fls); const bool lock_income = side->cfg()["income_lock"].to_bool(fls); const bool lock_team = side->cfg()["team_lock"].to_bool(fls); const bool lock_color = side->cfg()["color_lock"].to_bool(fls); const bool saved_game = connect_engine_.params().saved_game; // // AI Algorithm // int selection = 0; // We use an index-based loop in order to get the index of the selected option std::vector<config> ai_options; for(unsigned i = 0; i < ai_algorithms_.size(); i++) { ai_options.push_back(config_of("label", ai_algorithms_[i]->text)); if(ai_algorithms_[i]->id == side->ai_algorithm()) { selection = i; } } menu_button& ai_selection = find_widget<menu_button>(&row_grid, "ai_controller", false); ai_selection.set_values(ai_options, selection); ai_selection.connect_click_handler(std::bind(&mp_staging::on_ai_select, this, side, std::ref(ai_selection))); on_ai_select(side, ai_selection); // // Controller // std::vector<config> controller_names; for(const auto& controller : side->controller_options()) { controller_names.push_back(config_of("label", controller.second)); } menu_button& controller_selection = find_widget<menu_button>(&row_grid, "controller", false); controller_selection.set_values(controller_names, side->current_controller_index()); controller_selection.set_active(controller_names.size() > 1); controller_selection.connect_click_handler(std::bind(&mp_staging::on_controller_select, this, side, std::ref(row_grid))); on_controller_select(side, row_grid); // // Leader controls // button& leader_select = find_widget<button>(&row_grid, "select_leader", false); leader_select.set_active(!saved_game); connect_signal_mouse_left_click(leader_select, std::bind(&mp_staging::select_leader_callback, this, std::ref(window), side, std::ref(row_grid))); // // Team // std::vector<config> team_names; for(const auto& team : side->player_teams()) { team_names.push_back(config_of("label", team)); } menu_button& team_selection = find_widget<menu_button>(&row_grid, "side_team", false); // HACK: side->team() does not get its index from side->player_teams(), but rather side->team_names(). // As such, the index is off if there is only 1 playable team. This is a hack to make sure the menu_button // widget doesn't assert with the invalid initial selection. The connect_engine should be fixed once the GUI1 // dialog is dropped team_selection.set_values(team_names, std::min<int>(team_names.size() - 1, side->team())); team_selection.set_active(!saved_game); team_selection.connect_click_handler(std::bind(&mp_staging::on_team_select, this, std::ref(window), side, std::ref(team_selection), _3, _4)); // // Colors // std::vector<config> color_options; for(const auto& color : side->color_options()) { color_options.push_back(config_of ("label", font::get_color_string_pango(color)) ("icon", (formatter() << "misc/status.png~RC(magenta>" << color << ")").str()) ); } menu_button& color_selection = find_widget<menu_button>(&row_grid, "side_color", false); color_selection.set_values(color_options, side->color()); color_selection.set_active(!saved_game); color_selection.set_use_markup(true); color_selection.connect_click_handler(std::bind(&mp_staging::on_color_select, this, side, std::ref(row_grid))); // // Gold and Income // slider& slider_gold = find_widget<slider>(&row_grid, "side_gold_slider", false); slider_gold.set_value(side->cfg()["gold"].to_int(100)); connect_signal_notify_modified(slider_gold, std::bind( &mp_staging::on_side_slider_change<&ng::side_engine::set_gold>, this, side, std::ref(slider_gold))); slider& slider_income = find_widget<slider>(&row_grid, "side_income_slider", false); slider_income.set_value(side->cfg()["income"]); connect_signal_notify_modified(slider_income, std::bind( &mp_staging::on_side_slider_change<&ng::side_engine::set_income>, this, side, std::ref(slider_income))); // TODO: maybe display the saved values if(saved_game) { slider_gold.set_visible(widget::visibility::invisible); slider_income.set_visible(widget::visibility::invisible); } // // Gold, income, team, and color are only suggestions unless explicitly locked // if(!saved_game && ums) { team_selection.set_active(!lock_team); color_selection.set_active(!lock_color); slider_gold.set_active(!lock_gold); slider_income.set_active(!lock_income); } }
void plugins_context::set_accessor_int(const std::string & name, std::function<int(config)> func) { set_accessor(name, [func, name](const config& cfg) { return config_of(name, func(cfg)); }); }
LEVEL_RESULT playsingle_controller::play_scenario(const config& level) { 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(!this->is_skipping_replay()) { show_story(gui_->video(), get_scenario_name(), level.child_range("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; } } LOG_NG << "entering try... " << (SDL_GetTicks() - ticks()) << "\n"; try { play_scenario_init(); // clears level config; this->saved_game_.remove_snapshot(); if (!is_regular_game_end() && !linger_) { play_scenario_main_loop(); } if (game_config::exit_at_end) { exit(0); } const bool is_victory = get_end_level_data_const().is_victory; if(gamestate().gamedata_.phase() <= game_data::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(); const end_level_data& end_level = get_end_level_data_const(); if (!end_level.transient.custom_endlevel_music.empty()) { if (!is_victory) { 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 LEVEL_RESULT::VICTORY; // this is probably only a story scenario, i.e. has its endlevel in the prestart event } if(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 LEVEL_RESULT::VICTORY; } pump().fire(is_victory ? "victory" : "defeat"); { // Block for set_scontext_synced_base set_scontext_synced_base sync; pump().fire("scenario end"); } if(end_level.proceed_to_next_level) { gamestate().board_.heal_all_survivors(); } if(is_observer()) { gui2::show_transient_message(gui_->video(), _("Game Over"), _("The game is over.")); return LEVEL_RESULT::OBSERVER_END; } // 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. network::send_data(config_of ("info", config_of ("type", "termination") ("condition", "game over") ("result", is_victory ? "victory" : "defeat") )); // 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. const std::string& end_music = is_victory ? select_victory_music() : select_defeat_music(); if(end_music.empty() != true) { sound::play_music_once(end_music); } persist_.end_transaction(); return is_victory ? LEVEL_RESULT::VICTORY : LEVEL_RESULT::DEFEAT; } 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; } scoped_savegame_snapshot snapshot(*this); savegame::ingame_savegame save(saved_game_, *gui_, 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 LEVEL_RESULT::QUIT; } } return LEVEL_RESULT::QUIT; }
void tmp_create_game::post_show(twindow& window) { if(get_retval() == twindow::OK) { create_engine_.prepare_for_era_and_mods(); if(create_engine_.current_level_type() == ng::level::TYPE::CAMPAIGN || create_engine_.current_level_type() == ng::level::TYPE::SP_CAMPAIGN) { create_engine_.prepare_for_campaign(); } else if(create_engine_.current_level_type() == ng::level::TYPE::SCENARIO) { create_engine_.prepare_for_scenario(); } else { // This means define= doesn't work for randomly generated scenarios create_engine_.prepare_for_other(); } create_engine_.prepare_for_new_level(); create_engine_.get_parameters(); config_engine_->set_use_map_settings(use_map_settings_->get_widget_value(window)); if(!config_engine_->force_lock_settings()) { config_engine_->set_num_turns(turns_->get_widget_value(window)); config_engine_->set_village_gold(gold_->get_widget_value(window)); config_engine_->set_village_support(support_->get_widget_value(window)); config_engine_->set_xp_modifier(experience_->get_widget_value(window)); config_engine_->set_random_start_time(start_time_->get_widget_value(window)); config_engine_->set_fog_game(fog_->get_widget_value(window)); config_engine_->set_shroud_game(shroud_->get_widget_value(window)); config_engine_->write_parameters(); } config_engine_->set_mp_countdown(time_limit_->get_widget_value(window)); config_engine_->set_mp_countdown_init_time(init_turn_limit->get_widget_value(window)); config_engine_->set_mp_countdown_turn_bonus(turn_bonus_->get_widget_value(window)); config_engine_->set_mp_countdown_reservoir_time(reservior_->get_widget_value(window)); config_engine_->set_mp_countdown_action_bonus(action_bonus_->get_widget_value(window)); config_engine_->set_allow_observers(observers_->get_widget_value(window)); config_engine_->set_registered_users_only(registered_users_->get_widget_value(window)); config_engine_->set_oos_debug(strict_sync_->get_widget_value(window)); config_engine_->set_shuffle_sides(shuffle_sides_->get_widget_value(window)); // TODO: we rely on a hardcoded list in the WML file. Should we procedurally generate the contents? config_engine_->set_random_faction_mode(mp_game_settings::RANDOM_FACTION_MODE::from_int( find_widget<tcombobox>(&window, "random_faction_mode", false).get_value())); config options; for(const auto& mod_pair : visible_options_) { config& mod = options.add_child(mod_pair.first[0]); mod["id"] = mod_pair.first[1]; for(const auto& pair : mod_pair.second) { //TODO: change this to some key=value format as soon as we drop the old mp configure screen. mod.add_child("option", config_of("id", pair.first)("value", pair.second())); } } config_engine_->set_options(options); // Set game name const std::string name = find_widget<ttext_box>(&window, "game_name", false).get_value(); if(!name.empty() && (name != config_engine_->game_name_default())) { config_engine_->set_game_name(name); } // Set game password const std::string password = find_widget<ttext_box>(&window, "game_password", false).get_value(); if(!password.empty()) { config_engine_->set_game_password(password); } } }
// Same as play_test except that we return the results of play_game. int game_launcher::unit_test() { static bool first_time_unit = true; if(!cmdline_opts_.unit_test) { return 0; } if(!first_time_unit) return 0; first_time_unit = false; state_.classification().campaign_type = game_classification::CAMPAIGN_TYPE::TEST; state_.classification().campaign_define = "TEST"; state_.set_carryover_sides_start( config_of("next_scenario", test_scenario_) ); game_config_manager::get()-> load_game_config_for_game(state_.classification()); try { campaign_controller ccontroller(video(), state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types(), true); LEVEL_RESULT res = ccontroller.play_game(); if (!(res == LEVEL_RESULT::VICTORY) || lg::broke_strict()) { return 1; } } catch(wml_exception& e) { std::cerr << "Caught WML Exception:" << e.dev_message << std::endl; return 1; } savegame::clean_saves(state_.classification().label); if (cmdline_opts_.noreplaycheck) return 0; //we passed, huzzah! savegame::replay_savegame save(state_, compression::NONE); save.save_game_automatic(video(), false, "unit_test_replay"); //false means don't check for overwrite load_data_.reset(new savegame::load_game_metadata{ "unit_test_replay" , "", true, true, false }); if (!load_game()) { std::cerr << "Failed to load the replay!" << std::endl; return 3; //failed to load replay } try { campaign_controller ccontroller(video(), state_, game_config_manager::get()->game_config(), game_config_manager::get()->terrain_types(), true); LEVEL_RESULT res = ccontroller.play_replay(); if (!(res == LEVEL_RESULT::VICTORY)) { std::cerr << "Observed failure on replay" << std::endl; return 4; } } catch(wml_exception& e) { std::cerr << "WML Exception while playing replay: " << e.dev_message << std::endl; return 4; //failed with an error during the replay } return 0; //we passed, huzzah! }