From 5bfce15789796b7ed891482ce0e09b3cf2b15070 Mon Sep 17 00:00:00 2001 From: gfgtdf Date: Wed, 11 Jun 2014 20:33:42 +0200 Subject: [PATCH] move carryover handling out of playcampaign.cpp this also makes a small change in the savefile format: [endlevel] -> [end_level_data] in snapshots. we still have the "store_carryover" function in playcampaign.cpp which does the visual message. Note that the real carryover happens after linger mode while that message happens before linger mode this simplifies linger mode saves. --- src/carryover.cpp | 52 +++++++++++++++++++++++++++++++++-- src/carryover.hpp | 8 ++++-- src/game_board.cpp | 5 ++++ src/game_end_exceptions.hpp | 7 +++++ src/gamestatus.cpp | 11 ++++++++ src/play_controller.cpp | 2 +- src/playcampaign.cpp | 27 ++++++------------ src/playmp_controller.cpp | 1 + src/playsingle_controller.cpp | 7 +++-- src/saved_game.cpp | 14 ++++++++++ src/saved_game.hpp | 2 +- src/scripting/lua.cpp | 2 +- 12 files changed, 110 insertions(+), 28 deletions(-) diff --git a/src/carryover.cpp b/src/carryover.cpp index 1caf0607e644..621408353d0f 100644 --- a/src/carryover.cpp +++ b/src/carryover.cpp @@ -20,6 +20,7 @@ #include "team.hpp" #include "gamestatus.hpp" #include +#include carryover::carryover(const config& side) : add_(side["add"].to_bool()) @@ -33,6 +34,12 @@ carryover::carryover(const config& side) { BOOST_FOREACH(const config& u, side.child_range("unit")){ recall_list_.push_back(u); + config& u_back = recall_list_.back(); + u_back.remove_attribute("side"); + u_back.remove_attribute("goto_x"); + u_back.remove_attribute("goto_y"); + u_back.remove_attribute("x"); + u_back.remove_attribute("y"); } } @@ -122,6 +129,10 @@ const std::string carryover::to_string(){ return side; } +void carryover::set_gold(int gold){ + gold_ = gold; +} + void carryover::to_config(config& cfg){ config& side = cfg.add_child("side"); side["save_id"] = save_id_; @@ -135,7 +146,7 @@ void carryover::to_config(config& cfg){ side.add_child("unit", u_cfg); } -carryover_info::carryover_info(const config& cfg) +carryover_info::carryover_info(const config& cfg, bool from_snpashot) : carryover_sides_() , end_level_() , variables_(cfg.child_or_empty("variables")) @@ -144,9 +155,27 @@ carryover_info::carryover_info(const config& cfg) , next_scenario_(cfg["next_scenario"]) , next_underlying_unit_id_(cfg["next_underlying_unit_id"].to_int(0)) { + int turns_left = cfg["turns"].to_int() - cfg["turn_at"].to_int(); end_level_.read(cfg.child_or_empty("end_level_data")); - BOOST_FOREACH(const config& side, cfg.child_range("side")){ + BOOST_FOREACH(const config& side, cfg.child_range("side")) + { + if(side["lost"].to_bool(false) || !side["persistent"].to_bool(true)) + { + //this shouldnt happen outside a snpshot. + assert(from_snpashot); + continue; + } this->carryover_sides_.push_back(carryover(side)); + if(from_snpashot) + { + //adjust gold + int finishing_bonus_per_turn = cfg["map_villages_num"] * side["village_gold"] + side["income"]; + int finishing_bonus = std::max(0, finishing_bonus_per_turn * turns_left); + if(end_level_.gold_bonus) + { + carryover_sides_.back().set_gold(div100rounded((finishing_bonus + side["gold"]) * end_level_.carryover_percentage)); + } + } } wml_menu_items_.set_menu_items(cfg); @@ -296,3 +325,22 @@ carryover* carryover_info::get_side(std::string save_id){ } return NULL; } + + +void carryover_info::merge_old_carryover(const carryover_info& old_carryover) +{ + BOOST_FOREACH(const carryover & old_side, old_carryover.carryover_sides_) + { + std::vector::iterator iside = std::find_if( + carryover_sides_.begin(), + carryover_sides_.end(), + save_id_equals(old_side.get_save_id()) + ); + //add the side if don't already have it. + if(iside == carryover_sides_.end()) + { + this->carryover_sides_.push_back(old_side); + } + } +} + diff --git a/src/carryover.hpp b/src/carryover.hpp index 74c1bb440d2c..0afca8630e95 100644 --- a/src/carryover.hpp +++ b/src/carryover.hpp @@ -38,6 +38,7 @@ class carryover{ void initialize_team(config& side_cfg); const std::string to_string(); void to_config(config& cfg); + void set_gold(int gold); private: bool add_; std::string color_; @@ -65,8 +66,9 @@ class carryover_info{ , next_scenario_() , next_underlying_unit_id_() {} - // Turns config from a loaded savegame into carryover_info - explicit carryover_info(const config& cfg); + /// Turns config from a loaded savegame into carryover_info + /// @param from_snapshot true if cfg is a [snapshot], false if cfg is [carryover_sides(_start)] + explicit carryover_info(const config& cfg, bool from_snapshot = false); carryover* get_side(std::string save_id); std::vector& get_all_sides(); @@ -94,6 +96,8 @@ class carryover_info{ const std::string& next_scenario() const { return next_scenario_; } const config to_config(); + + void merge_old_carryover(const carryover_info& old_carryover); private: std::vector carryover_sides_; end_level_data end_level_; diff --git a/src/game_board.cpp b/src/game_board.cpp index dbbbba22067a..01e01f23accc 100644 --- a/src/game_board.cpp +++ b/src/game_board.cpp @@ -78,7 +78,9 @@ void game_board::all_survivors_to_recall() { if (teams_[un.side() - 1].persistent()) { un.new_turn(); un.new_scenario(); +#if 0 teams_[un.side() - 1].recall_list().push_back(un); +#endif } } } @@ -263,6 +265,9 @@ void game_board::write_config(config & cfg) const { //write the map cfg["map_data"] = map_->write(); + + //Used by the carryover calculations. + cfg["map_villages_num"] = map_->villages().size(); } temporary_unit_placer::temporary_unit_placer(unit_map& m, const map_location& loc, unit& u) diff --git a/src/game_end_exceptions.hpp b/src/game_end_exceptions.hpp index 63deae635ae6..d3fa6e34e423 100644 --- a/src/game_end_exceptions.hpp +++ b/src/game_end_exceptions.hpp @@ -228,6 +228,13 @@ struct end_level_data void write(config& cfg) const; void read(const config& cfg); + + config to_config() const + { + config r; + write(r); + return r; + } }; #endif /* ! GAME_END_EXCEPTIONS_HPP_INCLUDED */ diff --git a/src/gamestatus.cpp b/src/gamestatus.cpp index 8ef7eefc60d9..a216c04c1f6f 100644 --- a/src/gamestatus.cpp +++ b/src/gamestatus.cpp @@ -700,6 +700,17 @@ void convert_old_saves(config& cfg){ carryover_sides_start["next_underlying_unit_id"] = cfg["next_underlying_unit_id"]; } } + + if(config& snapshot = cfg.child("snapshot")) + { + //make [end_level] -> [end_level_data] since its alo called [end_level_data] in the carryover. + if(config& end_level = cfg.child("end_level") ) + { + snapshot.add_child("end_level_data", end_level); + snapshot.remove_child("end_level",0); + } + } + //1.12-1.13 end LOG_RG<<"cfg after conversion "< 1) { report << "\n" << t.current_player() << "\n"; } @@ -132,8 +121,6 @@ static void store_carryover(saved_game& gamestate, playsingle_controller& playco if (end_level.transient.carryover_report) { gui2::show_transient_message(disp.video(), title, report.str(), "", true); } - - gamestate.carryover_sides_start = sides.to_config(); } static void generate_scenario(config const*& scenario) @@ -266,6 +253,7 @@ static LEVEL_RESULT playsingle_scenario(const config& game_config, } } } + state_of_game.set_snapshot(playcontroller.to_config()); return res; } @@ -314,8 +302,9 @@ static LEVEL_RESULT playmp_scenario(const config& game_config, } } } - } + } + state_of_game.set_snapshot(playcontroller.to_config()); return res; } @@ -466,9 +455,9 @@ LEVEL_RESULT play_game(game_display& disp, saved_game& gamestate, save.save_game_automatic(disp.video(), true); } } - + + gamestate.convert_to_start_save(); recorder.clear(); - gamestate.remove_old_scenario(); // On DEFEAT, QUIT, or OBSERVER_END, we're done now diff --git a/src/playmp_controller.cpp b/src/playmp_controller.cpp index c31ecd277a7d..616fff78d7a6 100644 --- a/src/playmp_controller.cpp +++ b/src/playmp_controller.cpp @@ -623,6 +623,7 @@ void playmp_controller::do_idle_notification() void playmp_controller::maybe_linger() { + linger_ = true; if (!get_end_level_data_const().transient.linger_mode) { if(!is_host()) { // If we continue without lingering we need to diff --git a/src/playsingle_controller.cpp b/src/playsingle_controller.cpp index 1c54bb121968..ca891366ae9d 100644 --- a/src/playsingle_controller.cpp +++ b/src/playsingle_controller.cpp @@ -404,7 +404,7 @@ possible_end_play_signal playsingle_controller::play_scenario_main_loop(end_leve // 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.read(level_.child_or_empty("end_level_data")); end_level.transient.carryover_report = false; end_level.transient.disabled = true; end_level_struct els = { SKIP_TO_LINGER }; @@ -566,10 +566,11 @@ LEVEL_RESULT playsingle_controller::play_scenario( } // 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"; gameboard_.all_survivors_to_recall(); - gamestate_.set_snapshot(config()); + gamestate_.remove_snapshot(); if(!is_observer()) { persist_.end_transaction(); } @@ -1127,6 +1128,8 @@ bool playsingle_controller::is_host() const void playsingle_controller::maybe_linger() { + //Make sure [end_level_data] gets writen into the snapshot even when skipping linger mode. + linger_ = true; if (get_end_level_data_const().transient.linger_mode) { linger(); } diff --git a/src/saved_game.cpp b/src/saved_game.cpp index 308dd136358c..d4829f272419 100644 --- a/src/saved_game.cpp +++ b/src/saved_game.cpp @@ -45,6 +45,7 @@ #include "util.hpp" #include +#include static lg::log_domain log_engine("engine"); #define ERR_NG LOG_STREAM(err, log_engine) @@ -253,3 +254,16 @@ void saved_game::remove_old_scenario() replay_data = config(); replay_start_ = config(); } + +void saved_game::convert_to_start_save() +{ + assert(starting_pos_type_ == STARTINGPOS_SNAPSHOT); + carryover_info sides(starting_pos_, true); + sides.merge_old_carryover(carryover_info(carryover_sides)); + + carryover_sides_start = sides.to_config(); + replay_data = config(); + replay_start_ = config(); + carryover_sides = config(); + remove_snapshot(); +} diff --git a/src/saved_game.hpp b/src/saved_game.hpp index a7f79391d2c6..779ca9edb7fb 100644 --- a/src/saved_game.hpp +++ b/src/saved_game.hpp @@ -50,7 +50,7 @@ class saved_game { return starting_pos_type_ == STARTINGPOS_SNAPSHOT; } - + void convert_to_start_save(); config& get_starting_pos(); config& replay_start() { return replay_start_; } diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 0578502fd6f9..6e274b18a4c3 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -4026,7 +4026,7 @@ void LuaKernel::initialize() /// elsewhere (in the C++ code). /// Any child tags not in this list will be passed to Lua's on_load event. static char const *handled_file_tags[] = { - "color_palette", "color_range", "display", "endlevel", "era", + "color_palette", "color_range", "display", "end_level_data", "era", "event", "generator", "label", "lua", "map", "menu_item", "modification", "music", "options", "side", "sound_source", "story", "terrain_graphics", "time", "time_area", "tunnel",