diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 78878beda..f45fe243b 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -4302,6 +4302,21 @@ single Lua function, in ``hack/lua/plugins/pathable.lua``: ``cursor``. If ``skip_unrevealed`` is specified and true, do not draw unrevealed tiles. +reveal +====== + +Native functions provided by the `reveal` plugin: + +* ``void unhideFlood(pos)``: Unhides map tiles according to visibility rules, + starting from the given coordinates. This algorithm only processes adjacent + hidden tiles, so it must start on a hidden tile in order to have any effect. + It will not reveal hidden sections separated by already-unhidden tiles. + +Example of revealing a cavern that happens to have an open tile at the specified +coordinate:: + + unhideFlood({x=25, y=38, z=140}) + sort ==== diff --git a/docs/changelog.txt b/docs/changelog.txt index 8026a535a..ac57e53aa 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -52,6 +52,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## Lua - ``gui.Painter``: fixed error when calling ``viewport()`` method +- `reveal`: now exposes ``unhideFlood(pos)`` functionality to Lua - ``utils.processArgsGetopt()``: now returns negative numbers (e.g. ``-10``) in the list of positional parameters instead of treating it as an option string equivalent to ``-1 -0`` - ``utils.processArgsGetopt()``: now properly handles ``--`` like GNU ``getopt`` as a marker to treat all further parameters as non-options - ``utils.processArgsGetopt()``: now detects when required arguments to long-form options are missing diff --git a/library/include/PluginManager.h b/library/include/PluginManager.h index 8f73c8ec2..ec00e4ab0 100644 --- a/library/include/PluginManager.h +++ b/library/include/PluginManager.h @@ -33,6 +33,7 @@ distribution. #include #include "Core.h" +#include "DataFuncs.h" #include "RemoteClient.h" diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 822ab531b..de6388050 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -155,7 +155,7 @@ if(BUILD_SUPPORTED) dfhack_plugin(rename rename.cpp LINK_LIBRARIES lua PROTOBUFS rename) add_subdirectory(rendermax) dfhack_plugin(resume resume.cpp LINK_LIBRARIES lua) - dfhack_plugin(reveal reveal.cpp) + dfhack_plugin(reveal reveal.cpp LINK_LIBRARIES lua) dfhack_plugin(search search.cpp) dfhack_plugin(seedwatch seedwatch.cpp) dfhack_plugin(showmood showmood.cpp) diff --git a/plugins/lua/reveal.lua b/plugins/lua/reveal.lua new file mode 100644 index 000000000..f84cfed96 --- /dev/null +++ b/plugins/lua/reveal.lua @@ -0,0 +1,12 @@ +local _ENV = mkmodule('plugins.reveal') + +--[[ + + Native functions: + + * isEnabled() + * unhideFlood(pos) + +--]] + +return _ENV diff --git a/plugins/reveal.cpp b/plugins/reveal.cpp index 257dd5127..93e2041bd 100644 --- a/plugins/reveal.cpp +++ b/plugins/reveal.cpp @@ -2,10 +2,12 @@ #include #include #include + #include "Core.h" #include "Console.h" #include "Export.h" #include "PluginManager.h" + #include "modules/Maps.h" #include "modules/World.h" #include "modules/MapCache.h" @@ -329,66 +331,12 @@ command_result revtoggle (color_ostream &out, vector & params) } } -command_result revflood(color_ostream &out, vector & params) +// Unhides map tiles according to visibility, starting from the given +// coordinates. This algorithm only processes adjacent hidden tiles, so it must +// start on a hidden tile and it will not reveal hidden sections separated by +// already-unhidden tiles. +static void unhideFlood_internal(MapCache *MCache, const DFCoord &xy) { - for(size_t i = 0; i < params.size();i++) - { - if(params[i] == "help" || params[i] == "?") - return CR_WRONG_USAGE; - } - CoreSuspender suspend; - uint32_t x_max,y_max,z_max; - if (!Maps::IsValid()) - { - out.printerr("Map is not available!\n"); - return CR_FAILURE; - } - if(revealed != NOT_REVEALED) - { - out.printerr("This is only safe to use with non-revealed map.\n"); - return CR_FAILURE; - } - t_gamemodes gm; - World::ReadGameMode(gm); - if(!World::isFortressMode(gm.g_type) || gm.g_mode != game_mode::DWARF ) - { - out.printerr("Only in proper dwarf mode.\n"); - return CR_FAILURE; - } - int32_t cx, cy, cz; - Maps::getSize(x_max,y_max,z_max); - uint32_t tx_max = x_max * 16; - uint32_t ty_max = y_max * 16; - - Gui::getCursorCoords(cx,cy,cz); - if(cx == -30000) - { - out.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n"); - return CR_FAILURE; - } - DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); - MapCache * MCache = new MapCache; - df::tiletype tt = MCache->tiletypeAt(xy); - if(isWallTerrain(tt)) - { - out.printerr("Point the cursor at some empty space you want to be unhidden.\n"); - delete MCache; - return CR_FAILURE; - } - // hide all tiles, flush cache - Maps::getSize(x_max,y_max,z_max); - - for(size_t i = 0; i < world->map.map_blocks.size(); i++) - { - df::map_block * b = world->map.map_blocks[i]; - // change the hidden flag to 0 - for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++) - { - b->designation[x][y].bits.hidden = 1; - } - } - MCache->trash(); - typedef std::pair foo; std::stack < foo > flood; flood.push( foo(xy,false) ); @@ -500,8 +448,82 @@ command_result revflood(color_ostream &out, vector & params) flood.push(foo(DFCoord(current.x, current.y, current.z - 1), false)); } } +} + +// Lua entrypoint for unhideFlood_internal +static void unhideFlood(DFCoord pos) +{ + MapCache MCache; + // no environment or bounds checking needed. if anything is invalid, + // unhideFlood_internal will just exit immeditately + unhideFlood_internal(&MCache, pos); + MCache.WriteAll(); +} + +command_result revflood(color_ostream &out, vector & params) +{ + for(size_t i = 0; i < params.size();i++) + { + if(params[i] == "help" || params[i] == "?") + return CR_WRONG_USAGE; + } + CoreSuspender suspend; + uint32_t x_max,y_max,z_max; + if (!Maps::IsValid()) + { + out.printerr("Map is not available!\n"); + return CR_FAILURE; + } + if(revealed != NOT_REVEALED) + { + out.printerr("This is only safe to use with non-revealed map.\n"); + return CR_FAILURE; + } + t_gamemodes gm; + World::ReadGameMode(gm); + if(!World::isFortressMode(gm.g_type) || gm.g_mode != game_mode::DWARF ) + { + out.printerr("Only in proper dwarf mode.\n"); + return CR_FAILURE; + } + int32_t cx, cy, cz; + Maps::getSize(x_max,y_max,z_max); + uint32_t tx_max = x_max * 16; + uint32_t ty_max = y_max * 16; + + Gui::getCursorCoords(cx,cy,cz); + if(cx == -30000) + { + out.printerr("Cursor is not active. Point the cursor at some empty space you want to be unhidden.\n"); + return CR_FAILURE; + } + DFCoord xy ((uint32_t)cx,(uint32_t)cy,cz); + MapCache * MCache = new MapCache; + df::tiletype tt = MCache->tiletypeAt(xy); + if(isWallTerrain(tt)) + { + out.printerr("Point the cursor at some empty space you want to be unhidden.\n"); + delete MCache; + return CR_FAILURE; + } + // hide all tiles, flush cache + Maps::getSize(x_max,y_max,z_max); + + for(size_t i = 0; i < world->map.map_blocks.size(); i++) + { + df::map_block * b = world->map.map_blocks[i]; + // change the hidden flag to 0 + for (uint32_t x = 0; x < 16; x++) for (uint32_t y = 0; y < 16; y++) + { + b->designation[x][y].bits.hidden = 1; + } + } + MCache->trash(); + + unhideFlood_internal(MCache, xy); MCache->WriteAll(); delete MCache; + return CR_OK; } @@ -525,3 +547,8 @@ command_result revforget(color_ostream &out, vector & params) con.print("Reveal data forgotten!\n"); return CR_OK; } + +DFHACK_PLUGIN_LUA_FUNCTIONS { + DFHACK_LUA_FUNCTION(unhideFlood), + DFHACK_LUA_END +};