Merge pull request #181 from gfgtdf/gamestate_refactor

game_state refactor
This commit is contained in:
gfgtdf 2014-06-02 00:56:33 +02:00
commit 6a8827a071
27 changed files with 483 additions and 449 deletions

View file

@ -695,6 +695,7 @@ set(wesnoth-main_SRC
attack_prediction_display.cpp
callable_objects.cpp
commandline_options.cpp
carryover.cpp
config_cache.cpp
config_assign.cpp
controller_base.cpp

View file

@ -228,6 +228,7 @@ wesnoth_sources = Split("""
attack_prediction_display.cpp
callable_objects.cpp
commandline_options.cpp
carryover.cpp
config_cache.cpp
controller_base.cpp
desktop_util.cpp

View file

@ -250,7 +250,7 @@ bool ai_default_recruitment_stage::recruit_usage(const std::string& usage)
//FIXME: This message should be suppressed when WML author
//chooses the default recruitment pattern.
const std::string warning = "At difficulty level " +
resources::state_of_game->classification().difficulty + ", trying to recruit a:" +
resources::classification->difficulty + ", trying to recruit a:" +
usage + " but no unit of that type (usage=) is"
" available. Check the recruit and [ai]"
" recruitment_pattern keys for team '" +

View file

@ -362,7 +362,7 @@ bool recruitment_phase::recruit_usage(const std::string& usage)
//FIXME: This message should be suppressed when WML author
//chooses the default recruitment pattern.
const std::string warning = "At difficulty level " +
resources::state_of_game->classification().difficulty + ", trying to recruit a:" +
resources::classification->difficulty + ", trying to recruit a:" +
usage + " but no unit of that type (usage=) is"
" available. Check the recruit and [ai]"
" recruitment_pattern keys for team '" +

274
src/carryover.cpp Normal file
View file

@ -0,0 +1,274 @@
/*
Copyright (C) 2003 - 2014 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
#include "carryover.hpp"
#include "global.hpp"
#include "config.hpp"
#include "team.hpp"
#include "gamestatus.hpp"
#include <boost/foreach.hpp>
carryover::carryover(const config& side)
: add_(side["add"].to_bool())
, color_(side["color"])
, current_player_(side["current_player"])
, gold_(side["gold"].to_int())
, name_(side["name"])
, previous_recruits_(utils::set_split(side["previous_recruits"]))
, recall_list_()
, save_id_(side["save_id"])
{
BOOST_FOREACH(const config& u, side.child_range("unit")){
recall_list_.push_back(u);
}
}
carryover::carryover(const team& t, const int gold, const bool add)
: add_ (add)
, color_(t.color())
, current_player_(t.current_player())
, gold_(gold)
, name_(t.name())
, previous_recruits_(t.recruits())
, recall_list_()
, save_id_(t.save_id())
{
BOOST_FOREACH(const unit& u, t.recall_list()) {
recall_list_.push_back(config());
u.write(recall_list_.back());
}
}
static const int default_gold_qty = 100;
void carryover::transfer_all_gold_to(config& side_cfg){
int cfg_gold = side_cfg["gold"].to_int();
if(side_cfg["gold"].empty()) {
cfg_gold = default_gold_qty;
side_cfg["gold"] = cfg_gold;
}
if(add_ && gold_ > 0){
side_cfg["gold"] = cfg_gold + gold_;
}
else if(gold_ > cfg_gold){
side_cfg["gold"] = gold_;
}
gold_ = 0;
}
void carryover::transfer_all_recruits_to(config& side_cfg){
std::string can_recruit_str = utils::join(previous_recruits_, ",");
previous_recruits_.clear();
side_cfg["previous_recruits"] = can_recruit_str;
}
void carryover::transfer_all_recalls_to(config& side_cfg){
BOOST_FOREACH(const config & u_cfg, recall_list_) {
side_cfg.add_child("unit", u_cfg);
}
recall_list_.clear();
}
std::string carryover::get_recruits(bool erase){
// Join the previous recruits into a string.
std::string can_recruit_str = utils::join(previous_recruits_);
if ( erase )
// Clear the previous recruits.
previous_recruits_.clear();
return can_recruit_str;
}
void carryover::update_carryover(const team& t, const int gold, const bool add){
gold_ += gold;
add_ = add;
color_ = t.color();
current_player_ = t.current_player();
name_ = t.name();
previous_recruits_.insert(t.recruits().begin(), t.recruits().end());
BOOST_FOREACH(const unit& u, t.recall_list()) {
recall_list_.push_back(config());
u.write(recall_list_.back());
}
}
void carryover::initialize_team(config& side_cfg){
transfer_all_gold_to(side_cfg);
}
const std::string carryover::to_string(){
std::string side = "";
side.append("Side " + save_id_ + ": gold " + str_cast<int>(gold_) + " recruits " + get_recruits(false) + " units ");
BOOST_FOREACH(const config & u_cfg, recall_list_) {
side.append(u_cfg["name"].str() + ", ");
}
return side;
}
void carryover::to_config(config& cfg){
config& side = cfg.add_child("side");
side["save_id"] = save_id_;
side["gold"] = gold_;
side["add"] = add_;
side["color"] = color_;
side["current_player"] = current_player_;
side["name"] = name_;
side["previous_recruits"] = get_recruits(false);
BOOST_FOREACH(const config & u_cfg, recall_list_)
side.add_child("unit", u_cfg);
}
carryover_info::carryover_info(const config& cfg)
: carryover_sides_()
, end_level_()
, variables_(cfg.child_or_empty("variables"))
, rng_(cfg)
, wml_menu_items_()
, next_scenario_(cfg["next_scenario"])
{
end_level_.read(cfg.child_or_empty("end_level_data"));
BOOST_FOREACH(const config& side, cfg.child_range("side")){
this->carryover_sides_.push_back(carryover(side));
}
wml_menu_items_.set_menu_items(cfg);
}
std::vector<carryover>& carryover_info::get_all_sides() {
return carryover_sides_;
}
void carryover_info::add_side(const config& cfg) {
carryover_sides_.push_back(carryover(cfg));
}
void carryover_info::remove_side(const std::string& id) {
for (std::vector<carryover>::iterator it = carryover_sides_.begin();
it != carryover_sides_.end(); ++it) {
if (it->get_save_id() == id) {
carryover_sides_.erase(it);
break;
}
}
}
const end_level_data& carryover_info::get_end_level() const{
return end_level_;
}
void carryover_info::transfer_from(const team& t, int carryover_gold){
BOOST_FOREACH(carryover& side, carryover_sides_){
if(side.get_save_id() == t.save_id()){
side.update_carryover(t, carryover_gold, end_level_.carryover_add);
return;
}
}
carryover_sides_.push_back(carryover(t, carryover_gold, end_level_.carryover_add));
}
void carryover_info::transfer_all_to(config& side_cfg){
if(side_cfg["save_id"].empty()){
side_cfg["save_id"] = side_cfg["id"];
}
BOOST_FOREACH(carryover& side, carryover_sides_){
if(side.get_save_id() == side_cfg["save_id"]){
side.transfer_all_gold_to(side_cfg);
side.transfer_all_recalls_to(side_cfg);
side.transfer_all_recruits_to(side_cfg);
return;
}
}
//if no carryover was found for this side, check if starting gold is defined
if(!side_cfg.has_attribute("gold") || side_cfg["gold"].empty()){
side_cfg["gold"] = default_gold_qty;
}
}
void carryover_info::transfer_from(game_data& gamedata){
variables_ = gamedata.get_variables();
wml_menu_items_ = gamedata.get_wml_menu_items();
rng_ = gamedata.rng();
next_scenario_ = gamedata.next_scenario();
}
void carryover_info::transfer_to(config& level){
if(!end_level_.next_scenario_settings.empty()) {
level.merge_with(end_level_.next_scenario_settings);
}
if(!end_level_.next_scenario_append.empty())
{
level.append_children(end_level_.next_scenario_append);
}
end_level_.next_scenario_append = config();
end_level_.next_scenario_settings = config();
//if the game has been loaded from a snapshot, the existing variables will be the current ones
if(!level.has_child("variables")) {
level.add_child("variables", variables_);
}
config::attribute_value & seed_value = level["random_seed"];
if ( seed_value.empty() ) {
seed_value = rng_.get_random_seed();
level["random_calls"] = rng_.get_random_calls();
}
if(!level.has_child("menu_item")){
wml_menu_items_.to_config(level);
}
next_scenario_ = "";
}
const config carryover_info::to_config()
{
config cfg;
cfg["next_scenario"] = next_scenario_;
BOOST_FOREACH(carryover& c, carryover_sides_){
c.to_config(cfg);
}
config& end_level = cfg.add_child("end_level_data");
end_level_.write(end_level);
cfg["random_seed"] = rng_.get_random_seed();
cfg["random_calls"] = rng_.get_random_calls();
cfg.add_child("variables", variables_);
wml_menu_items_.to_config(cfg);
return cfg;
}
carryover* carryover_info::get_side(std::string save_id){
BOOST_FOREACH(carryover& side, carryover_sides_){
if(side.get_save_id() == save_id){
return &side;
}
}
return NULL;
}

106
src/carryover.hpp Normal file
View file

@ -0,0 +1,106 @@
#ifndef CARRYOVER_H_INCLUDED
#define CARRYOVER_H_INCLUDED
class team;
class config;
class game_data;
#include <vector>
#include <string>
#include <set>
#include "game_end_exceptions.hpp"
#include "simple_rng.hpp"
#include "game_events/wmi_container.hpp"
class carryover{
public:
carryover()
: add_ ()
, color_()
, current_player_()
, gold_()
, name_()
, previous_recruits_()
, recall_list_()
, save_id_()
{}
// Turns config from a loaded savegame into carryover_info
explicit carryover(const config& side);
carryover(const team& t, const int gold, const bool add);
~carryover(){}
const std::string& get_save_id() const{ return save_id_; }
void transfer_all_gold_to(config& side_cfg);
void transfer_all_recruits_to(config& side_cfg);
void transfer_all_recalls_to(config& side_cfg);
void update_carryover(const team& t, const int gold, const bool add);
void initialize_team(config& side_cfg);
const std::string to_string();
void to_config(config& cfg);
private:
bool add_;
std::string color_;
std::string current_player_;
int gold_;
std::string name_;
std::set<std::string> previous_recruits_;
// NOTE: we store configs instead of units because units often assume or
// assert that various resources:: are available, which is not the
// case between scenarios.
std::vector<config> recall_list_;
std::string save_id_;
std::string get_recruits(bool erase=false);
};
class carryover_info{
public:
carryover_info()
: carryover_sides_()
, end_level_()
, variables_()
, rng_()
, wml_menu_items_()
, next_scenario_()
{}
// Turns config from a loaded savegame into carryover_info
explicit carryover_info(const config& cfg);
carryover* get_side(std::string save_id);
std::vector<carryover>& get_all_sides();
void add_side(const config& cfg);
void add_side(const team& t, const int gold, const bool add);
void remove_side(const std::string& id);
void set_end_level(const end_level_data& end_level) { end_level_ = end_level; }
void transfer_from(const team& t, int carryover_gold);
void transfer_all_to(config& side_cfg);
void transfer_from(game_data& gamedata);
void transfer_to(config& level);
void set_variables(const config& vars) { variables_ = vars; }
const config& get_variables() const { return variables_; }
game_events::wmi_container& get_wml_menu_items() { return wml_menu_items_; }
const rand_rng::simple_rng& rng() const { return rng_; }
rand_rng::simple_rng& rng() { return rng_; }
const end_level_data& get_end_level() const;
const std::string& next_scenario() const { return next_scenario_; }
const config to_config();
private:
std::vector<carryover> carryover_sides_;
end_level_data end_level_;
config variables_;
rand_rng::simple_rng rng_;
game_events::wmi_container wml_menu_items_;
std::string next_scenario_; /**< the scenario coming next (for campaigns) */
};
#endif

View file

@ -159,7 +159,9 @@ editor_controller::~editor_controller()
resources::units = NULL;
resources::tod_manager = NULL;
resources::teams = NULL;
resources::state_of_game = NULL;
resources::classification = NULL;
resources::mp_settings = NULL;
}
EXIT_STATUS editor_controller::main_loop()

View file

@ -86,8 +86,10 @@ public:
context_manager_.gui().replace_overlay_map(&context_manager_.get_map_context().get_overlays());
resources::teams = &context_manager_.get_map_context().get_teams();
resources::classification = &context_manager_.get_map_context().get_game_state().classification();
resources::mp_settings = &context_manager_.get_map_context().get_game_state().mp_settings();
resources::state_of_game = &context_manager_.get_map_context().get_game_state();
context_manager_.gui().init_flags();
context_manager_.reload_map();

View file

@ -749,7 +749,7 @@ WML_HANDLER_FUNCTION(endlevel, /*event_info*/, cfg)
}
data.transient.disabled = true;
game_state *state_of_game = resources::state_of_game;
game_classification &classification = *resources::classification;
unit_map *units = resources::units;
// Remove 0-hp units from the unit map to avoid the following problem:
@ -781,17 +781,17 @@ WML_HANDLER_FUNCTION(endlevel, /*event_info*/, cfg)
std::string end_of_campaign_text = cfg["end_text"];
if (!end_of_campaign_text.empty()) {
state_of_game->classification().end_text = end_of_campaign_text;
classification.end_text = end_of_campaign_text;
}
config::attribute_value end_of_campaign_text_delay = cfg["end_text_duration"];
if (!end_of_campaign_text_delay.empty()) {
state_of_game->classification().end_text_duration =
end_of_campaign_text_delay.to_int(state_of_game->classification().end_text_duration);
classification.end_text_duration =
end_of_campaign_text_delay.to_int(classification.end_text_duration);
}
if(cfg.has_attribute("end_credits")) {
state_of_game->classification().end_credits = cfg["end_credits"].to_bool(true);
classification.end_credits = cfg["end_credits"].to_bool(true);
}

View file

@ -22,10 +22,10 @@
#include "gamestatus.hpp"
#include "actions/create.hpp"
#include "carryover.hpp"
#include "filesystem.hpp"
#include "formula_string_utils.hpp"
#include "game_config.hpp"
#include "game_events/handlers.hpp"
#include "game_preferences.hpp"
#include "gettext.hpp"
#include "log.hpp"
@ -73,253 +73,12 @@ static lg::log_domain log_enginerefac("enginerefac");
const std::string DEFAULT_DIFFICULTY("NORMAL");
carryover::carryover(const config& side)
: add_(side["add"].to_bool())
, color_(side["color"])
, current_player_(side["current_player"])
, gold_(side["gold"].to_int())
, name_(side["name"])
, previous_recruits_(utils::set_split(side["previous_recruits"]))
, recall_list_()
, save_id_(side["save_id"])
{
BOOST_FOREACH(const config& u, side.child_range("unit")){
recall_list_.push_back(u);
}
}
carryover::carryover(const team& t, const int gold, const bool add)
: add_ (add)
, color_(t.color())
, current_player_(t.current_player())
, gold_(gold)
, name_(t.name())
, previous_recruits_(t.recruits())
, recall_list_()
, save_id_(t.save_id())
{
BOOST_FOREACH(const unit& u, t.recall_list()) {
recall_list_.push_back(config());
u.write(recall_list_.back());
}
}
static const int default_gold_qty = 100;
void carryover::transfer_all_gold_to(config& side_cfg){
int cfg_gold = side_cfg["gold"].to_int();
if(side_cfg["gold"].empty()) {
cfg_gold = default_gold_qty;
side_cfg["gold"] = cfg_gold;
}
if(add_ && gold_ > 0){
side_cfg["gold"] = cfg_gold + gold_;
}
else if(gold_ > cfg_gold){
side_cfg["gold"] = gold_;
}
gold_ = 0;
}
void carryover::transfer_all_recruits_to(config& side_cfg){
std::string can_recruit_str = utils::join(previous_recruits_, ",");
previous_recruits_.clear();
side_cfg["previous_recruits"] = can_recruit_str;
}
void carryover::transfer_all_recalls_to(config& side_cfg){
BOOST_FOREACH(const config & u_cfg, recall_list_) {
side_cfg.add_child("unit", u_cfg);
}
recall_list_.clear();
}
std::string carryover::get_recruits(bool erase){
// Join the previous recruits into a string.
std::string can_recruit_str = utils::join(previous_recruits_);
if ( erase )
// Clear the previous recruits.
previous_recruits_.clear();
return can_recruit_str;
}
void carryover::update_carryover(const team& t, const int gold, const bool add){
gold_ += gold;
add_ = add;
color_ = t.color();
current_player_ = t.current_player();
name_ = t.name();
previous_recruits_.insert(t.recruits().begin(), t.recruits().end());
BOOST_FOREACH(const unit& u, t.recall_list()) {
recall_list_.push_back(config());
u.write(recall_list_.back());
}
}
void carryover::initialize_team(config& side_cfg){
transfer_all_gold_to(side_cfg);
}
const std::string carryover::to_string(){
std::string side = "";
side.append("Side " + save_id_ + ": gold " + str_cast<int>(gold_) + " recruits " + get_recruits(false) + " units ");
BOOST_FOREACH(const config & u_cfg, recall_list_) {
side.append(u_cfg["name"].str() + ", ");
}
return side;
}
void carryover::to_config(config& cfg){
config& side = cfg.add_child("side");
side["save_id"] = save_id_;
side["gold"] = gold_;
side["add"] = add_;
side["color"] = color_;
side["current_player"] = current_player_;
side["name"] = name_;
side["previous_recruits"] = get_recruits(false);
BOOST_FOREACH(const config & u_cfg, recall_list_)
side.add_child("unit", u_cfg);
}
carryover_info::carryover_info(const config& cfg)
: carryover_sides_()
, end_level_()
, variables_(cfg.child_or_empty("variables"))
, rng_(cfg)
, wml_menu_items_()
, next_scenario_(cfg["next_scenario"])
{
end_level_.read(cfg.child_or_empty("end_level_data"));
BOOST_FOREACH(const config& side, cfg.child_range("side")){
this->carryover_sides_.push_back(carryover(side));
}
wml_menu_items_.set_menu_items(cfg);
}
std::vector<carryover>& carryover_info::get_all_sides() {
return carryover_sides_;
}
void carryover_info::add_side(const config& cfg) {
carryover_sides_.push_back(carryover(cfg));
}
void carryover_info::remove_side(const std::string& id) {
for (std::vector<carryover>::iterator it = carryover_sides_.begin();
it != carryover_sides_.end(); ++it) {
if (it->get_save_id() == id) {
carryover_sides_.erase(it);
break;
}
}
}
const end_level_data& carryover_info::get_end_level() const{
return end_level_;
}
void carryover_info::transfer_from(const team& t, int carryover_gold){
BOOST_FOREACH(carryover& side, carryover_sides_){
if(side.get_save_id() == t.save_id()){
side.update_carryover(t, carryover_gold, end_level_.carryover_add);
return;
}
}
carryover_sides_.push_back(carryover(t, carryover_gold, end_level_.carryover_add));
}
void carryover_info::transfer_all_to(config& side_cfg){
if(side_cfg["save_id"].empty()){
side_cfg["save_id"] = side_cfg["id"];
}
BOOST_FOREACH(carryover& side, carryover_sides_){
if(side.get_save_id() == side_cfg["save_id"]){
side.transfer_all_gold_to(side_cfg);
side.transfer_all_recalls_to(side_cfg);
side.transfer_all_recruits_to(side_cfg);
return;
}
}
//if no carryover was found for this side, check if starting gold is defined
if(!side_cfg.has_attribute("gold") || side_cfg["gold"].empty()){
side_cfg["gold"] = default_gold_qty;
}
}
void carryover_info::transfer_from(game_data& gamedata){
variables_ = gamedata.get_variables();
wml_menu_items_ = gamedata.get_wml_menu_items();
rng_ = gamedata.rng();
next_scenario_ = gamedata.next_scenario();
}
void carryover_info::transfer_to(config& level){
//if the game has been loaded from a snapshot, the existing variables will be the current ones
if(!level.has_child("variables")) {
level.add_child("variables", variables_);
}
config::attribute_value & seed_value = level["random_seed"];
if ( seed_value.empty() ) {
seed_value = rng_.get_random_seed();
level["random_calls"] = rng_.get_random_calls();
}
if(!level.has_child("menu_item")){
wml_menu_items_.to_config(level);
}
next_scenario_ = "";
}
const config carryover_info::to_config()
{
config cfg;
cfg["next_scenario"] = next_scenario_;
BOOST_FOREACH(carryover& c, carryover_sides_){
c.to_config(cfg);
}
config& end_level = cfg.add_child("end_level_data");
end_level_.write(end_level);
cfg["random_seed"] = rng_.get_random_seed();
cfg["random_calls"] = rng_.get_random_calls();
cfg.add_child("variables", variables_);
wml_menu_items_.to_config(cfg);
return cfg;
}
carryover* carryover_info::get_side(std::string save_id){
BOOST_FOREACH(carryover& side, carryover_sides_){
if(side.get_save_id() == save_id){
return &side;
}
}
return NULL;
}
class team_builder {
public:
team_builder(const config& side_cfg,
const std::string &save_id, std::vector<team>& teams,
const config& level, gamemap& map, unit_map& units,
bool snapshot, const config &starting_pos)
const config &starting_pos)
: gold_info_ngold_(0)
, leader_configs_()
, level_(level)
@ -329,7 +88,6 @@ public:
, seen_ids_()
, side_(0)
, side_cfg_(side_cfg)
, snapshot_(snapshot)
, starting_pos_(starting_pos)
, t_(NULL)
, teams_(teams)
@ -385,7 +143,6 @@ protected:
std::set<std::string> seen_ids_;
int side_;
const config &side_cfg_;
bool snapshot_;
const config &starting_pos_;
team *t_;
std::vector<team> &teams_;
@ -733,9 +490,9 @@ void game_data::write_config(config_writer& out){
team_builder_ptr game_data::create_team_builder(const config& side_cfg,
std::string save_id, std::vector<team>& teams,
const config& level, gamemap& map, unit_map& units,
bool snapshot, const config& starting_pos)
const config& starting_pos)
{
return team_builder_ptr(new team_builder(side_cfg,save_id,teams,level,map,units,snapshot,starting_pos));
return team_builder_ptr(new team_builder(side_cfg, save_id, teams, level, map, units, starting_pos));
}
void game_data::build_team_stage_one(team_builder_ptr tb_ptr)
@ -1006,45 +763,18 @@ void convert_old_saves(config& cfg){
LOG_RG<<"cfg after conversion "<<cfg<<"\n";
}
void game_state::write_snapshot(config& cfg, game_display* gui) const
void game_state::write_snapshot(config& cfg) const
{
log_scope("write_game");
if(gui != NULL){
cfg["snapshot"] = true;
cfg["playing_team"] = str_cast(gui->playing_team());
cfg.merge_attributes(classification_.to_config());
game_events::write_events(cfg);
sound::write_music_play_list(cfg);
}
cfg["label"] = classification_.label;
cfg["abbrev"] = classification_.abbrev;
cfg["version"] = game_config::version;
cfg["completion"] = classification_.completion;
cfg["campaign"] = classification_.campaign;
cfg["campaign_type"] = lexical_cast<std::string> (classification_.campaign_type);
cfg["campaign_define"] = classification_.campaign_define;
cfg["campaign_extra_defines"] = utils::join(classification_.campaign_xtra_defines);
//TODO: move id_manager handling to play_controller
cfg["next_underlying_unit_id"] = str_cast(n_unit::id_manager::instance().get_save_id());
cfg["end_credits"] = classification_.end_credits;
cfg["end_text"] = classification_.end_text;
cfg["end_text_duration"] = str_cast<unsigned int>(classification_.end_text_duration);
cfg["difficulty"] = classification_.difficulty;
cfg["random_mode"] = classification_.random_mode;
if(resources::gamedata != NULL){
resources::gamedata->write_snapshot(cfg);
}
if(gui != NULL){
gui->labels().write(cfg);
}
}
void extract_summary_from_config(config& cfg_save, config& cfg_summary)

View file

@ -52,94 +52,6 @@ typedef boost::shared_ptr<team_builder> team_builder_ptr;
extern const std::string DEFAULT_DIFFICULTY;
class carryover{
public:
carryover()
: add_ ()
, color_()
, current_player_()
, gold_()
, name_()
, previous_recruits_()
, recall_list_()
, save_id_()
{}
// Turns config from a loaded savegame into carryover_info
explicit carryover(const config& side);
carryover(const team& t, const int gold, const bool add);
~carryover(){}
const std::string& get_save_id() const{ return save_id_; }
void transfer_all_gold_to(config& side_cfg);
void transfer_all_recruits_to(config& side_cfg);
void transfer_all_recalls_to(config& side_cfg);
void update_carryover(const team& t, const int gold, const bool add);
void initialize_team(config& side_cfg);
const std::string to_string();
void to_config(config& cfg);
private:
bool add_;
std::string color_;
std::string current_player_;
int gold_;
std::string name_;
std::set<std::string> previous_recruits_;
// NOTE: we store configs instead of units because units often assume or
// assert that various resources:: are available, which is not the
// case between scenarios.
std::vector<config> recall_list_;
std::string save_id_;
std::string get_recruits(bool erase=false);
};
class carryover_info{
public:
carryover_info()
: carryover_sides_()
, end_level_()
, variables_()
, rng_()
, wml_menu_items_()
, next_scenario_()
{}
// Turns config from a loaded savegame into carryover_info
explicit carryover_info(const config& cfg);
carryover* get_side(std::string save_id);
std::vector<carryover>& get_all_sides();
void add_side(const config& cfg);
void add_side(const team& t, const int gold, const bool add);
void remove_side(const std::string& id);
void set_end_level(const end_level_data& end_level) { end_level_ = end_level; }
void transfer_from(const team& t, int carryover_gold);
void transfer_all_to(config& side_cfg);
void transfer_from(game_data& gamedata);
void transfer_to(config& level);
void set_variables(const config& vars) { variables_ = vars; }
const config& get_variables() const { return variables_; }
game_events::wmi_container& get_wml_menu_items() { return wml_menu_items_; }
const rand_rng::simple_rng& rng() const { return rng_; }
rand_rng::simple_rng& rng() { return rng_; }
const end_level_data& get_end_level() const;
const std::string& next_scenario() const { return next_scenario_; }
const config to_config();
private:
std::vector<carryover> carryover_sides_;
end_level_data end_level_;
config variables_;
rand_rng::simple_rng rng_;
game_events::wmi_container wml_menu_items_;
std::string next_scenario_; /**< the scenario coming next (for campaigns) */
};
class game_data : public variable_set {
public:
@ -180,7 +92,7 @@ public:
//create an object responsible for creating and populating a team from a config
team_builder_ptr create_team_builder(const config& side_cfg, std::string save_id
, std::vector<team>& teams, const config& level, gamemap& map
, unit_map& units, bool snapshot, const config& starting_pos);
, unit_map& units, const config& starting_pos);
//do first stage of team initialization (everything except unit placement)
void build_team_stage_one(team_builder_ptr tb_ptr);
@ -262,7 +174,7 @@ public:
game_state& operator=(const game_state& state);
//write the gamestate into a config object
void write_snapshot(config& cfg, game_display* gui = NULL) const;
void write_snapshot(config& cfg) const;
//write the config information into a stream (file)
void write_config(config_writer& out) const;

View file

@ -13,6 +13,7 @@
*/
#include "mp_game_utils.hpp"
#include "carryover.hpp"
#include "config.hpp"
#include "dialogs.hpp"
#include "formula_string_utils.hpp"

View file

@ -30,6 +30,7 @@
#include "game_events/menu_item.hpp"
#include "game_events/pump.hpp"
#include "game_preferences.hpp"
#include "map_label.hpp"
#include "gettext.hpp"
#include "halo.hpp"
#include "loadscreen.hpp"
@ -78,13 +79,17 @@ static void clear_resources()
resources::persist = NULL;
resources::screen = NULL;
resources::soundsources = NULL;
resources::state_of_game = NULL;
resources::teams = NULL;
resources::tod_manager = NULL;
resources::tunnels = NULL;
resources::undo_stack = NULL;
resources::units = NULL;
resources::whiteboard = NULL;
resources::classification = NULL;
resources::mp_settings = NULL;
}
@ -140,12 +145,15 @@ play_controller::play_controller(const config& level, game_state& state_of_game,
resources::gamedata = &gamedata_;
resources::game_map = &gameboard_.map_;
resources::persist = &persist_;
resources::state_of_game = &gamestate_;
resources::teams = &gameboard_.teams_;
resources::tod_manager = &tod_manager_;
resources::undo_stack = undo_stack_.get();
resources::units = &gameboard_.units_;
resources::classification = &gamestate_.classification();
resources::mp_settings = &gamestate_.mp_settings();
persist_.start_transaction();
// Setup victory and defeat music
@ -183,8 +191,6 @@ void play_controller::init(CVideo& video){
// If i am wrong, use random_new_deterministic
recorder.set_skip(false);
bool snapshot = level_["snapshot"].to_bool();
if (level_["modify_placing"].to_bool()) {
LOG_NG << "modifying placing..." << std::endl;
place_sides_in_preferred_locations();
@ -223,7 +229,7 @@ void play_controller::init(CVideo& video){
}
}
team_builder_ptr tb_ptr = gamedata_.create_team_builder(side,
save_id, gameboard_.teams_, level_, gameboard_.map_, gameboard_.units_, snapshot, gamestate_.replay_start());
save_id, gameboard_.teams_, level_, gameboard_.map_, gameboard_.units_, gamestate_.replay_start());
++team_num;
gamedata_.build_team_stage_one(tb_ptr);
team_builders.push_back(tb_ptr);
@ -764,6 +770,15 @@ config play_controller::to_config() const
// Preserve the undo stack so that fog/shroud clearing is kept accurate.
undo_stack_->write(cfg.add_child("undo_stack"));
//Write the game events.
game_events::write_events(cfg);
if(gui_.get() != NULL){
cfg["playing_team"] = str_cast(gui_->playing_team());
gui_->labels().write(cfg);
sound::write_music_play_list(cfg);
}
return cfg;
}
@ -1466,7 +1481,7 @@ void play_controller::process_oos(const std::string& msg) const
message << _("The game is out of sync. It might not make much sense to continue. Do you want to save your game?");
message << "\n\n" << _("Error details:") << "\n\n" << msg;
savegame::oos_savegame save(to_config());
savegame::oos_savegame save(gamestate_, *gui_, to_config());
save.save_game_interactive(resources::screen->video(), message.str(), gui::YES_NO); // can throw end_level_exception
}
@ -1498,3 +1513,11 @@ void play_controller::toggle_accelerated_speed()
gui_->announce(_("Accelerated speed disabled!"), font::NORMAL_COLOR);
}
}
void play_controller::do_autosave()
{
savegame::autosave_savegame save(gamestate_, *gui_, to_config(), preferences::save_compression_format());
save.autosave(false, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES);
}

View file

@ -163,6 +163,8 @@ public:
bool is_skipping_replay() const { return skip_replay_;}
bool is_linger_mode() const { return linger_; }
void do_autosave();
events::mouse_handler& get_mouse_handler_base();
events::menu_handler& get_menu_handler() { return menu_handler_; }

View file

@ -20,12 +20,14 @@
#include "global.hpp"
#include "playcampaign.hpp"
#include "carryover.hpp"
#include "game_preferences.hpp"
#include "generators/map_create.hpp"
#include "gui/dialogs/message.hpp"
#include "gui/dialogs/transient_message.hpp"
#include "gui/widgets/window.hpp"
#include "playcampaign.hpp"
#include "persist_manager.hpp"
#include "playmp_controller.hpp"
#include "replay_controller.hpp"
@ -70,33 +72,6 @@ static void team_init(config& level, game_state& gamestate){
}
}
static void do_carryover_WML(config & level, game_state& gamestate){
if(gamestate.snapshot.child_or_empty("variables")["turn_number"].to_int(-1)<1){
carryover_info sides(gamestate.carryover_sides_start);
end_level_data end_level_ = sides.get_end_level();
if(!end_level_.next_scenario_settings.empty()) {
level.merge_with(end_level_.next_scenario_settings);
}
if(!end_level_.next_scenario_append.empty())
{
level.append_children(end_level_.next_scenario_append);
}
}
}
static void clear_carryover_WML (game_state & gamestate) {
if (gamestate.carryover_sides.has_child("end_level_data")) {
config & eld = gamestate.carryover_sides.child("end_level_data");
eld.clear_children("next_scenario_settings");
eld.clear_children("next_scenario_append");
}
}
static void store_carryover(game_state& 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";
@ -285,9 +260,7 @@ static LEVEL_RESULT playsingle_scenario(const config& game_config,
const int ticks = SDL_GetTicks();
config init_level = *level;
do_carryover_WML(init_level, state_of_game);
team_init(init_level, state_of_game);
clear_carryover_WML(state_of_game);
LOG_NG << "creating objects... " << (SDL_GetTicks() - ticks) << "\n";
playsingle_controller playcontroller(init_level, state_of_game, ticks, game_config, disp.video(), skip_replay);
@ -330,9 +303,7 @@ static LEVEL_RESULT playmp_scenario(const config& game_config,
const int ticks = SDL_GetTicks();
config init_level = *level;
do_carryover_WML(init_level, state_of_game);
team_init(init_level, state_of_game);
clear_carryover_WML(state_of_game);
playmp_controller playcontroller(init_level, state_of_game, ticks,
game_config, disp.video(), skip_replay, blindfold_replay, io_type == IO_SERVER);

View file

@ -20,6 +20,7 @@
#include "game_end_exceptions.hpp"
class display;
class game_display;
class game_state;
class config;

View file

@ -505,7 +505,7 @@ void playmp_controller::process_oos(const std::string& err_msg) const {
temp_buf << " \n";
}
savegame::oos_savegame save(to_config());
savegame::oos_savegame save(gamestate_, *gui_, to_config());
save.save_game_interactive(resources::screen->video(), temp_buf.str(), gui::YES_NO);
}

View file

@ -383,7 +383,7 @@ LEVEL_RESULT playsingle_controller::play_scenario(
// At the beginning of the scenario, save a snapshot as replay_start
if(gamestate_.snapshot.child_or_empty("variables")["turn_number"].to_int(-1)<1){
gamestate_.replay_start() = to_config();
gamestate_.write_snapshot(gamestate_.replay_start(), gui_.get());
gamestate_.write_snapshot(gamestate_.replay_start());
}
fire_preload();

View file

@ -97,9 +97,8 @@ turn_info::PROCESS_DATA_RESULT turn_info::handle_turn(
void turn_info::do_save()
{
if ((resources::state_of_game != NULL) && (resources::screen != NULL) && (resources::controller != NULL)) {
savegame::autosave_savegame save(*resources::state_of_game, *resources::screen, resources::controller->to_config(), preferences::save_compression_format());
save.autosave(false, preferences::autosavemax(), preferences::INFINITE_AUTO_SAVES);
if (resources::controller != NULL) {
resources::controller->do_autosave();
}
}

View file

@ -15,6 +15,9 @@
#include "global.hpp"
#include "replay_controller.hpp"
#include "carryover.hpp"
#include "actions/vision.hpp"
#include "game_end_exceptions.hpp"
#include "game_events/handlers.hpp"
@ -24,7 +27,6 @@
#include "mouse_handler_base.hpp"
#include "replay.hpp"
#include "random_new_deterministic.hpp"
#include "replay_controller.hpp"
#include "resources.hpp"
#include "savegame.hpp"
#include "synced_context.hpp"
@ -365,7 +367,7 @@ void replay_controller::process_oos(const std::string& msg) const
if (non_interactive()) {
throw game::game_error(message.str()); //throw end_level_exception(DEFEAT);
} else {
savegame::oos_savegame save(to_config());
savegame::oos_savegame save(gamestate_, *gui_, to_config());
save.save_game_interactive(resources::screen->video(), message.str(), gui::YES_NO); // can throw end_level_exception
}
}

View file

@ -33,4 +33,6 @@ namespace resources
actions::undo_list *undo_stack = NULL;
unit_map *units = NULL;
wb::manager *whiteboard = NULL;
game_classification *classification = NULL;
const mp_game_settings *mp_settings = NULL;
}

View file

@ -29,7 +29,8 @@ class team;
class tod_manager;
class unit_map;
class persist_manager;
class game_classification;
struct mp_game_settings;
namespace actions { class undo_list; }
namespace soundsource { class manager; }
@ -40,22 +41,23 @@ namespace wb { class manager; } //whiteboard manager
namespace resources
{
extern game_config_manager *config_manager;
extern play_controller *controller;
extern game_board *gameboard;
extern game_data *gamedata;
extern gamemap *game_map;
extern LuaKernel *lua_kernel; // Set by game_events::manager.
extern persist_manager *persist;
extern game_display *screen;
extern soundsource::manager *soundsources;
extern game_state *state_of_game;
extern std::vector<team> *teams;
extern ::tod_manager *tod_manager;
extern pathfind::manager *tunnels;
extern actions::undo_list *undo_stack;
extern unit_map *units;
extern wb::manager *whiteboard;
extern game_config_manager *config_manager;
extern play_controller *controller;
extern game_board *gameboard;
extern game_data *gamedata;
extern gamemap *game_map;
extern LuaKernel *lua_kernel; // Set by game_events::manager.
extern persist_manager *persist;
extern game_classification *classification;
extern game_display *screen;
extern const mp_game_settings *mp_settings;
extern soundsource::manager *soundsources;
extern std::vector<team> *teams;
extern ::tod_manager *tod_manager;
extern pathfind::manager *tunnels;
extern actions::undo_list *undo_stack;
extern unit_map *units;
extern wb::manager *whiteboard;
}
#endif

View file

@ -18,6 +18,7 @@
#include "savegame.hpp"
#include "carryover.hpp"
#include "dialogs.hpp" //FIXME: get rid of this as soon as the two remaining dialogs are moved to gui2
#include "format_time_summary.hpp"
#include "formula_string_utils.hpp"
@ -1040,8 +1041,8 @@ void autosave_savegame::create_filename()
set_filename(filename);
}
oos_savegame::oos_savegame(const config& snapshot_cfg)
: ingame_savegame(*resources::state_of_game, *resources::screen, snapshot_cfg, preferences::save_compression_format())
oos_savegame::oos_savegame(game_state& gamestate, game_display& gui, const config& snapshot_cfg)
: ingame_savegame(gamestate, gui, snapshot_cfg, preferences::save_compression_format())
{}
int oos_savegame::show_save_dialog(CVideo& video, const std::string& message, const gui::DIALOG_TYPE /*dialog_type*/)
@ -1084,7 +1085,7 @@ void ingame_savegame::create_filename()
void ingame_savegame::before_save()
{
savegame::before_save();
gamestate().write_snapshot(snapshot(), &gui_);
gamestate().write_snapshot(snapshot());
}
void ingame_savegame::write_game(config_writer &out) {

View file

@ -280,7 +280,7 @@ private:
class oos_savegame : public ingame_savegame
{
public:
oos_savegame(const config& snapshot_cfg);
oos_savegame(game_state& gamestate, game_display& gui, const config& snapshot_cfg);
private:
/** Display the save game dialog. */

View file

@ -1537,12 +1537,14 @@ static int impl_game_config_get(lua_State *L)
return_bool_attrib("debug", game_config::debug);
return_bool_attrib("debug_lua", game_config::debug_lua);
return_bool_attrib("mp_debug", game_config::mp_debug);
const mp_game_settings& mp_settings = *resources::mp_settings;
const game_classification & classification = *resources::classification;
const game_state & game_state_ = *resources::state_of_game;
return_string_attrib("campaign_type", lexical_cast<std::string>(game_state_.classification().campaign_type));
if(game_state_.classification().campaign_type==game_classification::MULTIPLAYER) {
return_cfgref_attrib("mp_settings", game_state_.mp_settings().to_config());
return_cfgref_attrib("era", resources::config_manager->game_config().find_child("era","id",game_state_.mp_settings().mp_era));
return_string_attrib("campaign_type", lexical_cast<std::string>(classification.campaign_type));
if(classification.campaign_type==game_classification::MULTIPLAYER) {
return_cfgref_attrib("mp_settings", mp_settings.to_config());
return_cfgref_attrib("era", resources::config_manager->game_config().find_child("era","id",mp_settings.mp_era));
//^ finds the era with name matching mp_era, and creates a lua reference from the config of that era.
//This code for SigurdFD, not the cleanest implementation but seems to work just fine.

View file

@ -20,7 +20,7 @@ struct map_location;
a class to check whether calculated ingame results match the results calculated during the original game.
note, that you shouldn't add new checkups to existent user actions or you might break replay compability by bringing the [checkups] tag of older saves in unorder.
so if you really want to add new checkups, you should wrap your checkup_instance->... call in a if(resources::state_of_game->classification().version ....) or similar.
so if you really want to add new checkups, you should wrap your checkup_instance->... call in a if(resources::state_of_game->classification.version ....) or similar.
*/
class checkup
{

View file

@ -210,7 +210,7 @@ void synced_context::pull_remote_user_input()
boost::shared_ptr<random_new::rng> synced_context::get_rng_for_action()
{
const std::string& mode = resources::state_of_game->classification().random_mode;
const std::string& mode = resources::classification->random_mode;
if(mode == "deterministic")
{
return boost::shared_ptr<random_new::rng>(new random_new::rng_deterministic(resources::gamedata->rng()));