Skip to content

Commit

Permalink
add terrain_mask function to lua gamemap object.
Browse files Browse the repository at this point in the history
  • Loading branch information
gfgtdf committed Oct 21, 2018
1 parent b43c132 commit cfd81d3
Show file tree
Hide file tree
Showing 4 changed files with 137 additions and 11 deletions.
35 changes: 25 additions & 10 deletions src/map/map.cpp
Expand Up @@ -208,20 +208,35 @@ std::string gamemap::write() const
}

void gamemap::overlay(const gamemap& m, map_location loc, const std::vector<overlay_rule>& rules, bool m_is_odd, bool ignore_special_locations)
{
overlay_impl(tiles_, starting_positions_, m.tiles_, m.starting_positions_, [this](auto&&... arg) { set_terrain(std::forward<decltype(arg)>(arg)...); }, loc, rules, m_is_odd, ignore_special_locations);
}

void gamemap::overlay_impl(
// const but changed via set_terrain
const t_translation::ter_map& m1,
starting_positions& m1_st,
const t_translation::ter_map& m2,
const starting_positions& m2_st,
std::function<void (const map_location&, const t_translation::terrain_code&, terrain_type_data::merge_mode, bool)> set_terrain,
map_location loc,
const std::vector<overlay_rule>& rules,
bool m_is_odd,
bool ignore_special_locations)
{
int xpos = loc.wml_x();
int ypos = loc.wml_y();

const int xstart = std::max<int>(0, -xpos);
const int xend = std::min<int>(m.total_width(), total_width() -xpos);
const int xend = std::min<int>(m2.w, m1.w -xpos);
const int xoffset = xpos;

const int ystart_even = std::max<int>(0, -ypos);
const int yend_even = std::min<int>(m.total_height(), total_height() - ypos);
const int yend_even = std::min<int>(m2.h, m1.h - ypos);
const int yoffset_even = ypos;

const int ystart_odd = std::max<int>(0, -ypos +(xpos & 1) -(m_is_odd ? 1 : 0));
const int yend_odd = std::min<int>(m.total_height(), total_height() - ypos +(xpos & 1) -(m_is_odd ? 1 : 0));
const int yend_odd = std::min<int>(m2.h, m1.h - ypos +(xpos & 1) -(m_is_odd ? 1 : 0));
const int yoffset_odd = ypos -(xpos & 1) + (m_is_odd ? 1 : 0);

for(int x1 = xstart; x1 != xend; ++x1) {
Expand All @@ -234,10 +249,10 @@ void gamemap::overlay(const gamemap& m, map_location loc, const std::vector<over
}
for(int y1 = ystart; y1 != yend; ++y1) {
const int x2 = x1 + xoffset;
const int y2 = y1 + yoffset;//ypos + ((xpos & 1) && (x1 & 1) ? 1 : 0);
const int y2 = y1 + yoffset;

const t_translation::terrain_code t = m.tiles_.get(x1,y1);
const t_translation::terrain_code current = tiles_.get(x2, y2);
const t_translation::terrain_code t = m2.get(x1,y1);
const t_translation::terrain_code current = m1.get(x2, y2);

if(t == t_translation::FOGGED || t == t_translation::VOID_TERRAIN) {
continue;
Expand All @@ -258,7 +273,7 @@ void gamemap::overlay(const gamemap& m, map_location loc, const std::vector<over
}

if (!rule) {
set_terrain(map_location(x2, y2, wml_loc()), t);
set_terrain(map_location(x2, y2, wml_loc()), t, terrain_type_data::BOTH, false);
}
else if(!rule->use_old_) {
set_terrain(map_location(x2, y2, wml_loc()), rule->terrain_ ? *rule->terrain_ : t , rule->mode_, rule->replace_if_failed_);
Expand All @@ -267,7 +282,7 @@ void gamemap::overlay(const gamemap& m, map_location loc, const std::vector<over
}

if (!ignore_special_locations) {
for(auto& pair : m.starting_positions_.left) {
for(auto& pair : m2_st.left) {

int x = pair.second.wml_x();
int y = pair.second.wml_y();
Expand All @@ -285,8 +300,8 @@ void gamemap::overlay(const gamemap& m, map_location loc, const std::vector<over
int y_new = y + ((x & 1 ) ? yoffset_odd : yoffset_even);
map_location pos_new = map_location(x_new, y_new, wml_loc());

starting_positions_.left.erase(pair.first);
starting_positions_.insert(starting_positions::value_type(pair.first, t_translation::coordinate(pos_new.x, pos_new.y)));
m1_st.left.erase(pair.first);
m1_st.insert(starting_positions::value_type(pair.first, t_translation::coordinate(pos_new.x, pos_new.y)));
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions src/map/map.hpp
Expand Up @@ -109,6 +109,18 @@ class gamemap
/** Overlays another map onto this one at the given position. */
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);

static void overlay_impl(
// const but changed via set_terrain
const t_translation::ter_map& m1,
starting_positions& m1_st,
const t_translation::ter_map& m2,
const starting_positions& m2_st,
std::function<void (const map_location&, const t_translation::terrain_code&, terrain_type_data::merge_mode, bool)> set_terrain,
map_location loc,
const std::vector<overlay_rule>& rules,
bool is_odd,
bool ignore_special_locations);

/** Effective map width. */
int w() const { return w_; }

Expand Down
99 changes: 99 additions & 0 deletions src/scripting/lua_terrainmap.cpp
Expand Up @@ -341,6 +341,103 @@ static int intf_get_terrain(lua_State *L)
return 1;
}

static std::vector<gamemap::overlay_rule> read_rules_vector(lua_State *L, int index)
{
std::vector<gamemap::overlay_rule> rules;
for (int i = 1, i_end = lua_rawlen(L, index); i <= i_end; ++i)
{
lua_rawgeti(L, index, i);
if(!lua_istable(L, -1)) {
return luaL_argerror(L, index, "rules must be a table of tables");
}
rules.push_back(gamemap::overlay_rule());
auto& rule = rules.back();
if(luaW_tableget(L, -1, "old")) {
rule.old_ = t_translation::read_list(luaW_tostring(L, -1));
lua_pop(L, 1);
}
if(luaW_tableget(L, -1, "new")) {
rule.new_ = t_translation::read_list(luaW_tostring(L, -1));
lua_pop(L, 1);
}

if(luaW_tableget(L, -1, "mode")) {
auto str = luaW_tostring(L, -1);
rule.mode_ = str == "base" ? terrain_type_data::BASE : (str == "overlay" ? terrain_type_data::OVERLAY : terrain_type_data::BOTH);
lua_pop(L, 1);
}

if(luaW_tableget(L, -1, "terrain")) {
const t_translation::ter_list terrain = t_translation::read_list(luaW_tostring(L, -1));
if(!terrain.empty()) {
rule.terrain_ = terrain[0];
}
lua_pop(L, 1);
}

if(luaW_tableget(L, -1, "use_old")) {
rule.use_old_ = luaW_toboolean(L, -1);
lua_pop(L, 1);
}

if(luaW_tableget(L, -1, "replace_if_failed")) {
rule.replace_if_failed_ = luaW_toboolean(L, -1);
lua_pop(L, 1);
}

lua_pop(L, 1);
}
return rules;
}
/**
* Reaplces part of the map.
* - Arg 1: map location.
* - Arg 2: map data string.
* - Arg 3: table for optional named arguments
* - is_odd: boolen, if Arg2 has the odd mapo format (as if it was cut from a odd map location)
* - ignore_special_locations: boolean
* - rules: table of tables
*/
static int intf_mg_terrain_mask(lua_State *L)
{
mapgen_gamemap& tm1 = luaW_checkterrainmap(L, 1);
map_location loc = luaW_checklocation(L, 2);
mapgen_gamemap& tm1 = luaW_checkterrainmap(L, 3);

bool is_odd = false;
bool ignore_special_locations = false;
std::vector<gamemap::overlay_rule> rules;

if(lua_istable(L, 4)) {
is_odd = luaW_table_get_def<bool>(L, 4, "is_odd", false);
ignore_special_locations = luaW_table_get_def<bool>(L, 4, "ignore_special_locations", false);

if(luaW_tableget(L, 4, "rules")) {
if(!lua_istable(L, -1)) {
return luaL_argerror(L, 4, "rules must be a table");
}
rules = read_rules_vector(L, -1)
lua_pop(L, 1);
}
}

board().map_->overlay(mask_map, loc, rules, is_odd, ignore_special_locations);

gamemap::overlay_impl(
tm1.tiles_,
tm1.starting_positions_,
tm2.tiles_,
tm2.starting_positions_,
[&](const map_location& loc, const t_translation::terrain_code& t, terrain_type_data::merge_mode mode, bool) { tm1.set_terrain(loc, t, mode); },
loc,
rules,
is_odd,
ignore_special_locations
);

return 0;
}

namespace lua_terrainmap {
std::string register_metatables(lua_State* L)
{
Expand All @@ -366,6 +463,8 @@ namespace lua_terrainmap {
lua_setfield(L, -2, "get_locations");
lua_pushcfunction(L, intf_mg_get_tiles_radius);
lua_setfield(L, -2, "get_tiles_radius");
lua_pushcfunction(L, intf_mg_terrain_mask);
lua_setfield(L, -2, "terrain_mask");

cmd_out << "Adding terrainmamap2 metatable...\n";

Expand Down
2 changes: 1 addition & 1 deletion src/scripting/lua_terrainmap.hpp
Expand Up @@ -88,7 +88,7 @@ class mapgen_gamemap
}
}
}

friend int intf_terrain_mask(lua_State *L);
private:
t_translation::ter_map tiles_;
starting_positions starting_positions_;
Expand Down

0 comments on commit cfd81d3

Please sign in to comment.