Forward-port 2008-12-01T19:42:47Z!joerg.hinrichs@alice-dsl.de from the 1.4 maintenance branch...

to development trunk; hand-applied the diff discarding all the
spurious format-only changes, and making the code aware of the changes
introduced by revisions 2008-03-30T13:49:03Z!joerg.hinrichs@alice-dsl.de..2008-04-01T21:51:29Z!joerg.hinrichs@alice-dsl.de in trunk.

This seems to work well testing up to the end of AToTB:2,
with just some "checksum mismatch" warnings that only
display on debug mode...
This commit is contained in:
Ignacio R. Morelle 2008-12-10 15:22:02 +00:00
parent 9eb5b01941
commit fb960ec58c
9 changed files with 53 additions and 9 deletions

View File

@ -58,6 +58,7 @@ Version 1.5.6+svn:
respectively, in [endlevel] or [campaign] tags. end_text_duration
is measured in milliseconds. (feature #10449)
* Miscellaneous and bug fixes:
* Fixed replays for single-player campaigns (bug #12005).
* New memory allocator introduced to the engine. It should
produce 5-10% savings in memory usage on 64-bit systems.
* Included extra headers for certain g++ versions (patch #1113).

View File

@ -35,6 +35,7 @@ Version 1.5.6+svn:
* Increased the cost of the Goblin Spearman from 8 to 9.
* Miscellaneous and bugfixes
* Fixed single-player campaign scenario replays.
* Fixed random memory corruption/assertion failure/massive memory leak
due to story screens.

View File

@ -86,7 +86,7 @@ void get_player_info(const config& cfg, game_state& gamestate,
scenarios. Snapshots and replays are loaded from savegames and
got their own gold information, which must not be altered here
*/
if ( (player != NULL) && (!snapshot) && (!replay) ) {
if ( (player != NULL) && (!snapshot) ) {
if(player->gold_add) {
ngold += player->gold;
} else if(player->gold >= ngold) {

View File

@ -530,6 +530,17 @@ game_state::game_state(const config& cfg, bool show_replay) :
const config* replay_start = cfg.child("replay_start");
if(replay_start != NULL) {
starting_pos = *replay_start;
//This is a quick hack to make replays for campaigns work again:
//The [player] information needs to be stored somewhere within the gamestate,
//because we need it later on when creating the replay savegame.
//We therefore put it inside the starting_pos, so it doesn't get lost.
//See also playcampaign::play_game, where after finishing the scenario the replay
//will be saved.
config::child_list player_list = cfg.get_children("player");
for (config::child_list::const_iterator p = player_list.begin(); p != player_list.end(); p++){
config& cfg_player = starting_pos.add_child("player");
cfg_player.merge_with(**p);
}
}
if(cfg.child("statistics")) {
@ -569,6 +580,18 @@ static void write_player(const player_info& player, config& cfg)
cfg["can_recruit"] = can_recruit_str;
}
void write_players(game_state& gamestate, config& cfg)
{
for(std::map<std::string, player_info>::const_iterator i=gamestate.players.begin();
i!=gamestate.players.end(); ++i)
{
config new_cfg;
write_player(i->second, new_cfg);
new_cfg["save_id"]=i->first;
cfg.add_child("player", new_cfg);
}
}
static void write_player(config_writer &out, const player_info& player)
{
out.write_key_val("name", player.name);

View File

@ -102,6 +102,13 @@ public:
/** Return the Nth player, or NULL if no such player exists. */
player_info* get_player(const std::string& id);
/**
* Loads the recall list.
*
* @param players Reference to the players section to load.
*/
void load_recall_list(const config::child_list& players);
std::vector<scoped_wml_variable*> scoped_variables;
std::map<std::string, wml_menu_item*> wml_menu_items;
@ -160,13 +167,6 @@ private:
mutable config temporaries; // lengths of arrays, etc.
const rand_rng::set_random_generator generator_setter; /**< Make sure that rng is initialized first */
friend struct variable_info;
/**
* Loads the recall list.
*
* @param players Reference to the players section to load.
*/
void load_recall_list(const config::child_list& players);
};
/**
@ -316,6 +316,7 @@ enum WRITE_GAME_MODE { WRITE_SNAPSHOT_ONLY, WRITE_FULL_GAME };
void read_save_file(const std::string& name, config& cfg, std::string* error_log);
void write_players(game_state& gamestate, config& cfg);
void write_game(const game_state& gamestate, config& cfg, WRITE_GAME_MODE mode=WRITE_FULL_GAME);
void write_game(config_writer &out, const game_state& gamestate, WRITE_GAME_MODE mode=WRITE_FULL_GAME);

View File

@ -416,6 +416,13 @@ LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_
gui::OK_CANCEL, _("Save Replay"), false, false) == 0) {
try {
config snapshot;
//If the starting position contains player information, use this for
//the replay savegame (this originally comes from the gamestate constructor,
//where the player stuff is added to the starting position to be used here.
config::child_list player_list = gamestate.starting_pos.get_children("player");
if (player_list.size() > 0) {
recorder.set_save_info(gamestate, player_list);
}
recorder.save_game(label, snapshot, gamestate.starting_pos);
} catch(game::save_game_failed&) {
gui::show_error_message(disp, _("The replay could not be saved"));
@ -506,7 +513,9 @@ LEVEL_RESULT play_game(display& disp, game_state& gamestate, const config& game_
// Sends scenario data
config cfg;
cfg.add_child("store_next_scenario", *scenario);
//Add the player section to the starting position so we can get the correct recall list
//when loading the replay later on
write_players(gamestate, gamestate.starting_pos);
// Adds player information, and other state
// information, to the configuration object
assert(cfg.child("store_next_scenario") != NULL);

View File

@ -412,10 +412,12 @@ LEVEL_RESULT playsingle_controller::play_scenario(const std::vector<config*>& st
}
// Add all the units that survived the scenario.
LOG_NG << "Add units that survived the scenario to the recall list.\n";
for(unit_map::iterator un = units_.begin(); un != units_.end(); ++un) {
player_info *player=gamestate_.get_player(teams_[un->second.side()-1].save_id());
if(player) {
LOG_NG << "Added unit " << un->second.id() << ", " << un->second.name() << "\n";
un->second.new_turn();
un->second.new_level();
player->available_units.push_back(un->second);

View File

@ -167,6 +167,12 @@ void replay::set_save_info(const game_state& save)
saveInfo_ = save;
}
void replay::set_save_info(const game_state& save, const config::child_list& players)
{
saveInfo_ = save;
saveInfo_.players.clear();
saveInfo_.load_recall_list(players);
}
void replay::set_save_info_completion(const std::string &st)
// This function is a kluge to get around the fact that replay objects carry

View File

@ -43,6 +43,7 @@ public:
explicit replay(const config& cfg);
void set_save_info(const game_state& save);
void set_save_info(const game_state& save, const config::child_list& players);
void set_save_info_completion(const std::string &st);
void set_skip(bool skip);