diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index f0871de4b..25ea7d150 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -111,7 +111,7 @@ if(BUILD_SUPPORTED) dfhack_plugin(deramp deramp.cpp) dfhack_plugin(debug debug.cpp LINK_LIBRARIES jsoncpp_lib_static) dfhack_plugin(dig dig.cpp) - dfhack_plugin(dig-now dig-now.cpp) + dfhack_plugin(dig-now dig-now.cpp LINK_LIBRARIES lua) dfhack_plugin(digFlood digFlood.cpp) add_subdirectory(diggingInvaders) dfhack_plugin(dwarfvet dwarfvet.cpp) diff --git a/plugins/dig-now.cpp b/plugins/dig-now.cpp index c19bf1263..1da6780b5 100644 --- a/plugins/dig-now.cpp +++ b/plugins/dig-now.cpp @@ -5,7 +5,9 @@ #include "DataFuncs.h" #include "PluginManager.h" #include "TileTypes.h" +#include "LuaTools.h" +#include "modules/Maps.h" #include "modules/MapCache.h" #include @@ -18,50 +20,16 @@ REQUIRE_GLOBAL(world); using namespace DFHack; -// returns true iff tile is in map bounds and was hidden before this function -// unhid it. -static bool unhide(MapExtras::MapCache &map, const DFCoord &pos) { - // ensures coords are in map bounds and ensures that the map block exists - // so we can unhide the tiles - if (!map.ensureBlockAt(pos)) - return false; - - df::tile_designation td = map.designationAt(pos); - if (!td.bits.hidden) - return false; - - td.bits.hidden = false; - return map.setDesignationAt(pos, td); -} +static void flood_unhide(color_ostream &out, const DFCoord &pos) { + auto L = Lua::Core::State; + Lua::StackUnwinder top(L); -// unhide adjacent tiles if hidden and flood fill unhidden state -static void flood_unhide(MapExtras::MapCache &map, const DFCoord &pos) { - df::tiletype tt = map.tiletypeAt(pos); - if (tileShape(tt) == df::tiletype_shape::WALL - && tileMaterial(tt) != df::tiletype_material::TREE) + if (!lua_checkstack(L, 2) + || !Lua::PushModulePublic(out, L, "plugins.reveal", "unhideFlood")) return; - for (int32_t xoff = -1; xoff <= 1; ++xoff) { - for (int32_t yoff = -1; yoff <= 1; ++yoff) { - if (xoff == 0 && yoff == 0) - continue; - if (unhide(map, DFCoord(pos.x+xoff, pos.y+yoff, pos.z))) - flood_unhide(map, DFCoord(pos.x+xoff, pos.y+yoff, pos.z)); - } - } - - DFCoord pos_below(pos.x, pos.y, pos.z-1); - if (LowPassable(tt) && unhide(map, pos_below)) - flood_unhide(map, pos_below); - - // note that checking HighPassable for the current tile gives false - // positives. You have to check LowPassable for the tile above. - DFCoord pos_above(pos.x, pos.y, pos.z+1); - if (map.ensureBlockAt(pos_above) - && LowPassable(map.tiletypeAt(pos_above)) - && unhide(map, pos_above)) { - flood_unhide(map, pos_above); - } + Lua::Push(L, pos); + Lua::SafeCall(out, L, 1, 0); } // inherit flags from passable tiles above and propagate to passable tiles below @@ -69,7 +37,7 @@ static void propagate_vertical_flags(MapExtras::MapCache &map, const DFCoord &pos) { df::tile_designation td = map.designationAt(pos); - if (!map.ensureBlockAt(DFCoord(pos.x, pos.y, pos.z-1))) { + if (!map.ensureBlockAt(DFCoord(pos.x, pos.y, pos.z+1))) { // only the sky above td.bits.light = true; td.bits.outside = true; @@ -248,7 +216,6 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, dig_tile(out, map, pos_below, df::tile_dig_designation::Ramp)) { clean_ramps(map, pos_below); - flood_unhide(map, pos); // if we successfully dug out the ramp below, that took care // of the ramp top here return true; @@ -296,16 +263,14 @@ static bool dig_tile(color_ostream &out, MapExtras::MapCache &map, pos.x, pos.y, pos.z, designation); } - // fail if no change to tile + // fail if unhandled or no change to tile if (target_type == df::tiletype::Void || target_type == tt) return false; dig_type(map, pos, target_type); - // set flags for current and adjacent tiles - unhide(map, pos); - flood_unhide(map, pos); // in case we breached a cavern - propagate_vertical_flags(map, pos); // for new channels + // let light filter down to newly exposed tiles + propagate_vertical_flags(map, pos); return true; } @@ -334,9 +299,12 @@ command_result dig_dug(color_ostream &out, std::vector &) { uint32_t endx, endy, endz; Maps::getTileSize(endx, endy, endz); - // use the proxy layer for the layer material-setting ease-of-use functions + // use the proxy layer for the layer material-setting ease-of-use functions. MapExtras::MapCache map; + // tracks which positions to unhide + std::vector dug_coords; + for (uint32_t z = 0; z <= endz; ++z) { for (uint32_t y = 0; y <= endy; ++y) { for (uint32_t x = 0; x <= endx; ++x) { @@ -353,6 +321,7 @@ command_result dig_dug(color_ostream &out, std::vector &) { td = map.designationAt(pos); td.bits.dig = df::tile_dig_designation::No; map.setDesignationAt(pos, td); + dug_coords.push_back(pos); } } else if (td.bits.smooth > 0) { bool want_engrave = td.bits.smooth == 2; @@ -380,6 +349,14 @@ command_result dig_dug(color_ostream &out, std::vector &) { map.WriteAll(); + // unhide newly dug tiles. we can't do this in the loop above since our + // MapCache wouldn't detect the changes made by reveal.unhideFlood() without + // invalidating and reinitializing on every call. + for (DFCoord pos : dug_coords) { + if (Maps::getTileDesignation(pos)->bits.hidden) + flood_unhide(out, pos); + } + // Force the game to recompute its walkability cache world->reindex_pathfinding = true;