// To remove radundant informaion in the clientside internal programmflow // I want to remove these values from mp_settings so i need to readd them here static void add_multiplayer_classification(config& multiplayer, saved_game& state) { multiplayer["mp_scenario"] = state.get_scenario_id(); multiplayer["mp_scenario_name"] = state.get_starting_pos()["name"]; multiplayer["difficulty_define"] = state.classification().difficulty; multiplayer["mp_campaign"] = state.classification().campaign; }
playsingle_controller::playsingle_controller(const config& level, saved_game& state_of_game, const int ticks, const config& game_config, CVideo& video, bool skip_replay) : play_controller(level, state_of_game, ticks, game_config, video, skip_replay), cursor_setter(cursor::NORMAL), textbox_info_(), replay_sender_(recorder), network_reader_(), turn_data_(replay_sender_, network_reader_), end_turn_(false), player_type_changed_(false), replaying_(false), skip_next_turn_(false), do_autosaves_(false), level_result_(NONE) { // game may need to start in linger mode if (state_of_game.classification().completion == "victory" || state_of_game.classification().completion == "defeat") { LOG_NG << "Setting linger mode.\n"; browse_ = linger_ = true; } ai::game_info ai_info; ai::manager::set_ai_info(ai_info); ai::manager::add_observer(this) ; }
void level_to_gamestate(const config& level, saved_game& state) { game_classification::CAMPAIGN_TYPE type = state.classification().campaign_type; bool show_connect = state.mp_settings().show_connect; state = saved_game(level); state.classification().campaign_type = type; state.mp_settings().show_connect = show_connect; }
static void show_carryover_message(saved_game& gamestate, playsingle_controller& playcontroller, display& disp, const end_level_data& end_level, const LEVEL_RESULT res){ bool has_next_scenario = !resources::gamedata->next_scenario().empty() && resources::gamedata->next_scenario() != "null"; //maybe this can be the case for scenario that only contain a story and end during the prestart event ? if(resources::teams->size() < 1){ return; } std::ostringstream report; std::string title; bool obs = playcontroller.is_observer(); if (obs) { title = _("Scenario Report"); } else if (res == LEVEL_RESULT::VICTORY) { title = _("Victory"); report << "<b>" << _("You have emerged victorious!") << "</b>\n\n"; } else { title = _("Defeat"); report << _("You have been defeated!") << "\n"; } assert(resources::teams); //We need to write the carryover amount to the team thats why we need non const std::vector<team>& teams = *resources::teams; int persistent_teams = 0; BOOST_FOREACH(const team &t, teams) { if (t.persistent()){ ++persistent_teams; } } if (persistent_teams > 0 && ((has_next_scenario && end_level.proceed_to_next_level)|| gamestate.classification().campaign_type == game_classification::CAMPAIGN_TYPE::TEST)) { gamemap map = playcontroller.get_map_const(); tod_manager tod = playcontroller.get_tod_manager_const(); int turns_left = std::max<int>(0, tod.number_of_turns() - tod.turn()); BOOST_FOREACH(team &t, teams) { if (!t.persistent() || t.lost()) { continue; } int finishing_bonus_per_turn = map.villages().size() * t.village_gold() + t.base_income(); int finishing_bonus = t.carryover_bonus() ? finishing_bonus_per_turn * turns_left : 0; t.set_carryover_gold(div100rounded((t.gold() + finishing_bonus) * t.carryover_percentage())); if(!t.is_local_human()) { continue; } if (persistent_teams > 1) { report << "\n<b>" << t.current_player() << "</b>\n"; } playcontroller.report_victory(report, t, finishing_bonus_per_turn, turns_left, finishing_bonus); } }
void level_to_gamestate(const config& level, saved_game& state) { game_classification::CAMPAIGN_TYPE type = state.classification().campaign_type; state = saved_game(level); state.classification().campaign_type = type; // Any replay data is only temporary and should be removed from // the level data in case we want to save the game later. if (const config& replay_data = level.child("replay")) { LOG_NW << "setting replay\n"; recorder = replay(replay_data); if (!recorder.empty()) { recorder.set_skip(false); recorder.set_to_end(); } } //save id setting was moved to play_controller. }
void start_client(const config& game_config, saved_game& state, const std::string& host) { const config* game_config_ptr = &game_config; // This function does not refer to an addon database, it calls filesystem functions. // For the sanity of the mp lobby, this list should be fixed for the entire lobby session, // even if the user changes the contents of the addon directory in the meantime. std::vector<std::string> installed_addons = ::installed_addons(); DBG_MP << "starting client" << std::endl; preferences::admin_authentication_reset r; wesnothd_connection_ptr connection; config lobby_config; gui2::dialogs::loading_screen::display([&]() { std::tie(connection, lobby_config) = open_connection(host); }); if(!connection) { return; } mp_workflow_helper_ptr workflow_helper; bool re_enter = false; do { workflow_helper.reset(new mp_workflow_helper(*game_config_ptr, state, connection.get(), nullptr)); // A return of false means a config reload was requested, so do that and then loop. re_enter = !enter_lobby_mode(workflow_helper, installed_addons, lobby_config); if(re_enter) { game_config_manager* gcm = game_config_manager::get(); gcm->reload_changed_game_config(); gcm->load_game_config_for_game(state.classification()); // NOTE: Using reload_changed_game_config only doesn't seem to work here game_config_ptr = &gcm->game_config(); installed_addons = ::installed_addons(); // Refresh the installed add-on list for this session. connection->send_data(config("refresh_lobby")); } } while(re_enter); }
replay_controller::replay_controller(const config& level, saved_game& state_of_game, const int ticks, const config& game_config, CVideo& video) : play_controller(level, state_of_game, ticks, game_config, video, false), saved_game_start_(saved_game_), gameboard_start_(gamestate_.board_), tod_manager_start_(level), current_turn_(1), is_playing_(false), show_everything_(false), show_team_(state_of_game.classification().campaign_type == game_classification::MULTIPLAYER ? 0 : 1) { // Our parent class correctly detects that we are loading a game. However, // we are not loading mid-game, so from here on, treat this as not loading // a game. (Allows turn_1 et al. events to fire at the correct time.) loading_game_ = false; init(); reset_replay(); }
static void show_carryover_message(saved_game& gamestate, playsingle_controller& playcontroller, display& disp, const end_level_data& end_level, const LEVEL_RESULT res){ bool has_next_scenario = !resources::gamedata->next_scenario().empty() && resources::gamedata->next_scenario() != "null"; //maybe this can be the case for scenario that only contain a story and end during the prestart event ? if(resources::teams->size() < 1){ return; } std::ostringstream report; std::string title; bool obs = playcontroller.is_observer(); if (obs) { title = _("Scenario Report"); } else if (res == VICTORY) { title = _("Victory"); report << "<b>" << _("You have emerged victorious!") << "</b>\n\n"; } else { title = _("Defeat"); report << _("You have been defeated!") << "\n"; } std::vector<team> teams = playcontroller.get_teams_const(); int persistent_teams = 0; BOOST_FOREACH(const team &t, teams) { if (t.persistent()){ ++persistent_teams; } } if (persistent_teams > 0 && ((has_next_scenario && end_level.proceed_to_next_level)|| gamestate.classification().campaign_type == game_classification::TEST)) { gamemap map = playcontroller.get_map_const(); // NOTE: this function uses game_config::village_income/game_config::base_income which is teh same for all teams // the function that actualy does the carryover (carryover.cpp) uses team.base_income() / team.village_gold() since 1.13 // which can be different for every team int finishing_bonus_per_turn = map.villages().size() * game_config::village_income + game_config::base_income; tod_manager tod = playcontroller.get_tod_manager_const(); int turns_left = std::max<int>(0, tod.number_of_turns() - tod.turn()); int finishing_bonus = (end_level.gold_bonus && turns_left > -1) ? finishing_bonus_per_turn * turns_left : 0; BOOST_FOREACH(const team &t, teams) { if (!t.persistent() || t.lost() || !t.is_human()) { continue; } int carryover_gold = div100rounded((t.gold() + finishing_bonus) * end_level.carryover_percentage); if (persistent_teams > 1) { report << "\n<b>" << t.current_player() << "</b>\n"; } playcontroller.report_victory(report, carryover_gold, t.gold(), finishing_bonus_per_turn, turns_left, finishing_bonus); } }
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; }
scenariostart_savegame::scenariostart_savegame(saved_game &gamestate, const compression::format compress_saves) : savegame(gamestate, compress_saves) { set_filename(gamestate.classification().label); }
void start_local_game_commandline(const config& game_config, saved_game& state, const commandline_options& cmdline_opts) { DBG_MP << "starting local MP game from commandline" << std::endl; // The setup is done equivalently to lobby MP games using as much of existing // code as possible. This means that some things are set up that are not // needed in commandline mode, but they are required by the functions called. preferences::set_message_private(false); DBG_MP << "entering create mode" << std::endl; // Set the default parameters state.clear(); // This creates these parameters with default values defined in mp_game_settings.cpp mp_game_settings& parameters = state.mp_settings(); // Hardcoded default values parameters.mp_era = "era_default"; parameters.name = "multiplayer_The_Freelands"; // Default values for which at getter function exists parameters.num_turns = settings::get_turns(""); parameters.village_gold = settings::get_village_gold(""); parameters.village_support = settings::get_village_support(""); parameters.xp_modifier = settings::get_xp_modifier(""); // Do not use map settings if --ignore-map-settings commandline option is set if(cmdline_opts.multiplayer_ignore_map_settings) { DBG_MP << "ignoring map settings" << std::endl; parameters.use_map_settings = false; } else { parameters.use_map_settings = true; } // None of the other parameters need to be set, as their creation values above are good enough for CL mode. // In particular, we do not want to use the preferences values. state.classification().campaign_type = game_classification::CAMPAIGN_TYPE::MULTIPLAYER; // [era] define. if(cmdline_opts.multiplayer_era) { parameters.mp_era = *cmdline_opts.multiplayer_era; } if(const config& cfg_era = game_config.find_child("era", "id", parameters.mp_era)) { state.classification().era_define = cfg_era["define"].str(); } else { std::cerr << "Could not find era '" << parameters.mp_era << "'\n"; return; } // [multiplayer] define. if(cmdline_opts.multiplayer_scenario) { parameters.name = *cmdline_opts.multiplayer_scenario; } if(const config& cfg_multiplayer = game_config.find_child("multiplayer", "id", parameters.name)) { state.classification().scenario_define = cfg_multiplayer["define"].str(); } else { std::cerr << "Could not find [multiplayer] '" << parameters.name << "'\n"; return; } game_config_manager::get()->load_game_config_for_game(state.classification()); state.set_carryover_sides_start( config {"next_scenario", parameters.name} ); state.expand_random_scenario(); state.expand_mp_events(); state.expand_mp_options(); // Should number of turns be determined from scenario data? if(parameters.use_map_settings && state.get_starting_pos()["turns"]) { DBG_MP << "setting turns from scenario data: " << state.get_starting_pos()["turns"] << std::endl; parameters.num_turns = state.get_starting_pos()["turns"]; } DBG_MP << "entering connect mode" << std::endl; statistics::fresh_stats(); { ng::connect_engine_ptr connect_engine(new ng::connect_engine(state, true, nullptr)); // Update the parameters to reflect game start conditions connect_engine->start_game_commandline(cmdline_opts); } if(resources::recorder && cmdline_opts.multiplayer_label) { std::string label = *cmdline_opts.multiplayer_label; resources::recorder->add_log_data("ai_log","ai_label",label); } unsigned int repeat = (cmdline_opts.multiplayer_repeat) ? *cmdline_opts.multiplayer_repeat : 1; for(unsigned int i = 0; i < repeat; i++){ saved_game state_copy(state); campaign_controller controller(state_copy, game_config, game_config_manager::get()->terrain_types()); controller.play_game(); } }
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 level_to_gamestate(const config& level, saved_game& state) { game_classification::CAMPAIGN_TYPE type = state.classification().campaign_type; state = saved_game(level); state.classification().campaign_type = type; }