add [unit_type_fix] in [scenario], [era] etc

fixes #1451

Currently advancements can be changed in two ways:
1) Via [advancefrom], this causes OOS in multiplayer
2) Via certain campaign etra defines, this has other disadvantages see

The new [unit_type_fix] that is accepted in [scenario], [multiplayer],
[era], [modification] , [campaign] and [ressource] changes the advancement
of a unit type only for one game and has non of the disadvantages of
the other two methods.

We should also deprecate the other two methods.
This commit is contained in:
gfgtdf 2019-03-01 01:50:47 +01:00
parent 3c172f7303
commit e4c4ca7572
4 changed files with 68 additions and 0 deletions

View file

@ -97,6 +97,7 @@ static void copy_persistent(const config& src, config& dst)
static const std::set<std::string> tags {
"terrain_graphics",
"unit_type_fix",
"lua"};
for (const std::string& attr : attrs)
@ -167,6 +168,9 @@ play_controller::play_controller(const config& level, saved_game& state_of_game,
{
copy_persistent(level, level_);
for(const config& unit_type_fix : level_.child_range("unit_type_fix")) {
unit_types.apply_scenario_fix(unit_type_fix);
}
resources::controller = this;
resources::persist = &persist_;
resources::recorder = replay_.get();
@ -188,6 +192,7 @@ play_controller::play_controller(const config& level, saved_game& state_of_game,
play_controller::~play_controller()
{
unit_types.remove_scenario_fixes();
hotkey::delete_all_wml_hotkeys();
clear_resources();
}

View file

@ -331,6 +331,11 @@ void saved_game::load_mod(const std::string& type, const std::string& id, size_t
for(const config& modlua : cfg.child_range("lua")) {
this->starting_point_.add_child_at_total("lua", modlua, pos++);
}
// Copy unit_type_fix
for(const config& modlua : cfg.child_range("unit_type_fix")) {
this->starting_point_.add_child_at_total("unit_type_fix", modlua, pos++);
}
// Copy load_resource
for(const config& load_resource : cfg.child_range("load_resource")) {

View file

@ -33,6 +33,7 @@
#include "gui/dialogs/loading_screen.hpp"
#include <boost/regex.hpp>
#include <boost/range/algorithm_ext/erase.hpp>
#include <locale>
@ -1423,6 +1424,59 @@ const unit_race* unit_type_data::find_race(const std::string& key) const
return i != races_.end() ? &i->second : nullptr;
}
void unit_type::apply_scenario_fix(const config& cfg)
{
if(auto p_setxp = cfg.get("set_experience")) {
experience_needed_ = p_setxp->to_int();
}
if(auto attr = cfg.get("set_advances_to")) {
advances_to_ = utils::split(attr->str());
}
if(auto attr = cfg.get("set_cost")) {
cost_ = attr->to_int(1);
}
if(auto attr = cfg.get("add_advancement")) {
for(const auto& str : utils::split(attr->str())) {
advances_to_.push_back(str);
}
}
if(auto attr = cfg.get("remove_advancement")) {
for(const auto& str : utils::split(attr->str())) {
boost::remove_erase(advances_to_, str);
}
}
}
void unit_type_data::apply_scenario_fix(const config& cfg)
{
unit_type_map::iterator itor = types_.find(cfg["type"].str());
// This might happen if units of another era are requested (for example for savegames)
if(itor != types_.end()) {
itor->second.apply_scenario_fix(cfg);
}
else {
// should we give an error message?
}
}
void unit_type::remove_scenario_fixes()
{
advances_to_.clear();
const std::string& advances_to_val = cfg_["advances_to"];
if(advances_to_val != "null" && !advances_to_val.empty()) {
advances_to_ = utils::split(advances_to_val);
}
experience_needed_ = cfg_["experience"].to_int(500);
cost_ = cfg_["cost"].to_int(1);
}
void unit_type_data::remove_scenario_fixes()
{
for(auto& pair : types_) {
pair.second.remove_scenario_fixes();
}
}
void unit_type::check_id(std::string& id)
{
assert(!id.empty());

View file

@ -275,6 +275,8 @@ public:
/// Attention: Filters in resistance-abilities will be ignored.
int resistance_against(const std::string& damage_name, bool attacker) const;
void apply_scenario_fix(const config& cfg);
void remove_scenario_fixes();
private:
/// Generates (and returns) a trimmed config suitable for use with units.
const config & build_unit_cfg() const;
@ -375,6 +377,8 @@ public:
/** Checks if the [hide_help] tag contains these IDs. */
bool hide_help(const std::string &type_id, const std::string &race_id) const;
void apply_scenario_fix(const config& cfg);
void remove_scenario_fixes();
private:
/** Parses the [hide_help] tag. */
void read_hide_help(const config &cfg);