move [terrain_mask] to lua
and implement it using wesnoth.terrain_mask.
This also fixes an issue where [terrain_mask] would not remove
removed villages from the teams villages list after [terrain_mask].
This also adds an alignment parameter to [terrain_mask].
(cherry-picked from commit 09c56ef2fe
)
This commit is contained in:
parent
e4c170f249
commit
42af4c3378
7 changed files with 45 additions and 126 deletions
|
@ -965,3 +965,44 @@ function wesnoth.wml_actions.store_unit_defense(cfg)
|
|||
end
|
||||
wml.variables[cfg.variable or "terrain_defense"] = defense
|
||||
end
|
||||
|
||||
function wml_actions.terrain_mask(cfg)
|
||||
cfg = helper.parsed(cfg)
|
||||
|
||||
local alignment = cfg.alignment
|
||||
local is_odd = false
|
||||
local border = cfg.border
|
||||
local mask = cfg.mask
|
||||
local x = cfg.x or helper.wml_error("[terrain_mask] missing x attribute")
|
||||
local y = cfg.y or helper.wml_error("[terrain_mask] missing y attribute")
|
||||
if alignment == "even" then
|
||||
is_odd = false
|
||||
elseif alignment == "odd" then
|
||||
is_odd = true
|
||||
elseif alignment == "raw" then
|
||||
--todo: maybe rename this value?
|
||||
is_odd = (number % 2 != 0)
|
||||
elseif border == false then
|
||||
is_odd = true
|
||||
else
|
||||
is_odd = false
|
||||
-- the old [terrain_mask] code would insert the terrain as one
|
||||
-- tile to the northwest from the specified hex.
|
||||
-- todo: deprecate this strange behaviour or at least not make it
|
||||
-- the default behaviour anymore.
|
||||
local new_loc = wesnoth.map.get_direction({x, y}, "nw")
|
||||
x, y = new_loc[1], new_loc[2]
|
||||
end
|
||||
local rules = {}
|
||||
for rule in wml.child_range(cfg, 'rule') do
|
||||
rules[#rules] = rule
|
||||
end
|
||||
if cfg.mask_file then
|
||||
mask = wesnoth.read_file(cfg.mask_file)
|
||||
end
|
||||
wesnoth.terrain_mask({x, y}, mask, {
|
||||
is_odd = is_odd,
|
||||
rules = rules,
|
||||
ignore_special_locations = cfg.ignore_special_locations,
|
||||
})
|
||||
end
|
||||
|
|
|
@ -303,7 +303,7 @@ IMPLEMENT_ACTION(apply_mask)
|
|||
|
||||
void editor_action_apply_mask::perform_without_undo(map_context& mc) const
|
||||
{
|
||||
mc.map().overlay(mask_, config(), {0, 0});
|
||||
mc.map().overlay(mask_, {0, 0, wml_loc()});
|
||||
mc.set_needs_terrain_rebuild();
|
||||
}
|
||||
|
||||
|
|
|
@ -283,10 +283,6 @@ boost::optional<std::string> game_board::replace_map(const gamemap & newmap) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
void game_board::overlay_map(const gamemap & mask_map, const config & cfg, map_location loc) {
|
||||
map_->overlay_old(mask_map, cfg, loc);
|
||||
}
|
||||
|
||||
bool game_board::change_terrain(const map_location &loc, const std::string &t_str,
|
||||
const std::string & mode_str, bool replace_if_failed)
|
||||
{
|
||||
|
|
|
@ -155,8 +155,7 @@ public:
|
|||
// Manipulator from actionwml
|
||||
|
||||
bool try_add_unit_to_recall_list(const map_location& loc, const unit_ptr u);
|
||||
boost::optional<std::string> replace_map (const gamemap & r);
|
||||
void overlay_map(const gamemap & o, const config & cfg, map_location loc);
|
||||
boost::optional<std::string> replace_map(const gamemap & r);
|
||||
|
||||
bool change_terrain(const map_location &loc, const std::string &t,
|
||||
const std::string & mode, bool replace_if_failed); //used only by lua
|
||||
|
|
|
@ -862,41 +862,6 @@ WML_HANDLER_FUNCTION(store_time_of_day,, cfg)
|
|||
}
|
||||
}
|
||||
|
||||
/// Creating a mask of the terrain
|
||||
WML_HANDLER_FUNCTION(terrain_mask,, cfg)
|
||||
{
|
||||
map_location loc = cfg_to_loc(cfg, 1, 1);
|
||||
|
||||
gamemap mask_map(resources::gameboard->map().tdata(), "");
|
||||
|
||||
try {
|
||||
if(!cfg["mask_file"].empty()) {
|
||||
const std::string& maskfile = filesystem::get_wml_location(cfg["mask_file"].str());
|
||||
|
||||
if(filesystem::file_exists(maskfile)) {
|
||||
mask_map.read(filesystem::read_file(maskfile), false);
|
||||
} else {
|
||||
throw incorrect_map_format_error("Invalid file path");
|
||||
}
|
||||
} else {
|
||||
mask_map.read(cfg["mask"], false);
|
||||
}
|
||||
} catch(const incorrect_map_format_error&) {
|
||||
ERR_NG << "terrain mask is in the incorrect format, and couldn't be applied" << std::endl;
|
||||
return;
|
||||
} catch(const wml_exception& e) {
|
||||
e.show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cfg["border"].to_bool(true)) {
|
||||
mask_map.add_fog_border();
|
||||
}
|
||||
|
||||
resources::gameboard->overlay_map(mask_map, cfg.get_parsed_config(), loc);
|
||||
game_display::get_singleton()->needs_rebuild(true);
|
||||
}
|
||||
|
||||
WML_HANDLER_FUNCTION(tunnel,, cfg)
|
||||
{
|
||||
const bool remove = cfg["remove"].to_bool(false);
|
||||
|
|
|
@ -207,74 +207,6 @@ std::string gamemap::write() const
|
|||
return t_translation::write_game_map(tiles_, starting_positions_, t_translation::coordinate{ border_size(), border_size() }) + "\n";
|
||||
}
|
||||
|
||||
void gamemap::overlay_old(const gamemap& m, const config& rules_cfg, map_location loc)
|
||||
{
|
||||
int xpos = loc.x;
|
||||
int ypos = loc.y;
|
||||
//const config::const_child_itors &rules = rules_cfg.child_range("rule");
|
||||
std::vector<overlay_rule> rules(rules_cfg.child_count("rule"));
|
||||
for(std::size_t i = 0; i <rules.size(); ++i)
|
||||
{
|
||||
const config& cfg = rules_cfg.child("rule", i);
|
||||
rules[i].old_ = t_translation::read_list(cfg["old"].str());
|
||||
rules[i].new_ = t_translation::read_list(cfg["new"].str());
|
||||
rules[i].mode_ = cfg["layer"] == "base" ? terrain_type_data::BASE : cfg["layer"] == "overlay" ? terrain_type_data::OVERLAY : terrain_type_data::BOTH;
|
||||
const t_translation::ter_list& terrain = t_translation::read_list(cfg["terrain"].str());
|
||||
if(!terrain.empty()) {
|
||||
rules[i].terrain_ = terrain[0];
|
||||
}
|
||||
rules[i].use_old_ = cfg["use_old"].to_bool();
|
||||
rules[i].replace_if_failed_ = cfg["replace_if_failed"].to_bool();
|
||||
}
|
||||
|
||||
const int xstart = std::max<int>(-border_size(), -xpos - border_size());
|
||||
const int ystart = std::max<int>(-border_size(), -ypos - border_size() - ((xpos & 1) ? 1 : 0));
|
||||
const int xend = std::min<int>(m.w() + border_size(), w() + border_size() - xpos);
|
||||
const int yend = std::min<int>(m.h() + border_size(), h() + border_size() - ypos);
|
||||
|
||||
for(int x1 = xstart; x1 < xend; ++x1) {
|
||||
for(int y1 = ystart; y1 < yend; ++y1) {
|
||||
const int x2 = x1 + xpos;
|
||||
const int y2 = y1 + ypos + ((xpos & 1) && (x1 & 1) ? 1 : 0);
|
||||
|
||||
const t_translation::terrain_code t = m[{x1,y1}];
|
||||
const t_translation::terrain_code current = (*this)[{x2, y2}];
|
||||
|
||||
if(t == t_translation::FOGGED || t == t_translation::VOID_TERRAIN) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// See if there is a matching rule
|
||||
const overlay_rule* rule = nullptr;
|
||||
for(const overlay_rule& current_rule : rules)
|
||||
{
|
||||
if(!current_rule.old_.empty() && !t_translation::terrain_matches(current, current_rule.old_)) {
|
||||
continue;
|
||||
}
|
||||
if(!current_rule.new_.empty() && !t_translation::terrain_matches(t, current_rule.new_)) {
|
||||
continue;
|
||||
}
|
||||
rule = ¤t_rule;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!rule) {
|
||||
set_terrain(map_location(x2, y2), t);
|
||||
}
|
||||
else if(!rule->use_old_) {
|
||||
set_terrain(map_location(x2, y2), rule->terrain_ ? *rule->terrain_ : t , rule->mode_, rule->replace_if_failed_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rules_cfg["ignore_special_locations"].to_bool(false)) {
|
||||
for(auto& pair : m.starting_positions_.left) {
|
||||
starting_positions_.left.erase(pair.first);
|
||||
starting_positions_.insert(starting_positions::value_type(pair.first, t_translation::coordinate(pair.second.x + xpos, pair.second.y + ypos+ ((xpos & 1) && (pair.second.x & 1) ? 1 : 0))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gamemap::overlay(const gamemap& m, map_location loc, const std::vector<overlay_rule>& rules, bool m_is_odd, bool ignore_special_locations)
|
||||
{
|
||||
int xpos = loc.wml_x();
|
||||
|
@ -510,16 +442,3 @@ std::vector<map_location> gamemap::parse_location_range(const std::string &x, co
|
|||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void gamemap::add_fog_border()
|
||||
{
|
||||
t_translation::ter_map tiles_new(tiles_.w + 1, tiles_.h + 1);
|
||||
for (int x = 0, x_end = tiles_new.w; x != x_end; ++x) {
|
||||
for (int y = 0, y_end = tiles_new.h; y != y_end; ++y) {
|
||||
tiles_new.get(x, y) = (x == 0 || y == 0) ? t_translation::VOID_TERRAIN : tiles_.get(x - 1, y - 1);
|
||||
}
|
||||
}
|
||||
++w_;
|
||||
++h_;
|
||||
tiles_ = tiles_new;
|
||||
}
|
||||
|
|
|
@ -107,8 +107,7 @@ public:
|
|||
};
|
||||
|
||||
/** Overlays another map onto this one at the given position. */
|
||||
void overlay_old(const gamemap& m, const config& rules, map_location loc);
|
||||
void overlay(const gamemap& m, map_location loc, const std::vector<overlay_rule>& rules, bool is_odd, bool ignore_special_locations);
|
||||
void overlay(const gamemap& m, map_location loc, const std::vector<overlay_rule>& rules = std::vector<overlay_rule>(), bool is_odd = false, bool ignore_special_locations = false);
|
||||
|
||||
/** Effective map width. */
|
||||
int w() const { return w_; }
|
||||
|
@ -229,7 +228,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
void add_fog_border();
|
||||
|
||||
protected:
|
||||
t_translation::ter_map tiles_;
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue