expose core flood unhide logic to Lua

refactor is a straight copy-paste. this code could really stand some
cleanup (unused vars, unnecessary use of the MapCache layer, forced
allocation of all blocks even if they are not being unhidden, etc.), but
that can come in a later PR.
develop
myk002 2021-06-02 14:49:19 -07:00
parent 32d0d4209b
commit fb8d6614c7
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
5 changed files with 117 additions and 60 deletions

@ -4297,6 +4297,21 @@ single Lua function, in ``hack/lua/plugins/pathable.lua``:
``cursor``. If ``skip_unrevealed`` is specified and true, do not draw ``cursor``. If ``skip_unrevealed`` is specified and true, do not draw
unrevealed tiles. 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 sort
==== ====

@ -33,6 +33,7 @@ distribution.
#include <vector> #include <vector>
#include "Core.h" #include "Core.h"
#include "DataFuncs.h"
#include "RemoteClient.h" #include "RemoteClient.h"

@ -155,7 +155,7 @@ if(BUILD_SUPPORTED)
dfhack_plugin(rename rename.cpp LINK_LIBRARIES lua PROTOBUFS rename) dfhack_plugin(rename rename.cpp LINK_LIBRARIES lua PROTOBUFS rename)
add_subdirectory(rendermax) add_subdirectory(rendermax)
dfhack_plugin(resume resume.cpp LINK_LIBRARIES lua) 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(search search.cpp)
dfhack_plugin(seedwatch seedwatch.cpp) dfhack_plugin(seedwatch seedwatch.cpp)
dfhack_plugin(showmood showmood.cpp) dfhack_plugin(showmood showmood.cpp)

@ -0,0 +1,12 @@
local _ENV = mkmodule('plugins.reveal')
--[[
Native functions:
* isEnabled()
* unhideFlood(pos)
--]]
return _ENV

@ -2,10 +2,12 @@
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <vector> #include <vector>
#include "Core.h" #include "Core.h"
#include "Console.h" #include "Console.h"
#include "Export.h" #include "Export.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "modules/Maps.h" #include "modules/Maps.h"
#include "modules/World.h" #include "modules/World.h"
#include "modules/MapCache.h" #include "modules/MapCache.h"
@ -329,66 +331,12 @@ command_result revtoggle (color_ostream &out, vector<string> & params)
} }
} }
command_result revflood(color_ostream &out, vector<string> & params) // Unhides map tiles according to visibility, starting from the given
{ // coordinates. This algorithm only processes adjacent hidden tiles, so it must
for(size_t i = 0; i < params.size();i++) // start on a hidden tile and it will not reveal hidden sections separated by
{ // already-unhidden tiles.
if(params[i] == "help" || params[i] == "?") static void unhideFlood_internal(MapCache *MCache, const DFCoord &xy)
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 <DFCoord, bool> foo; typedef std::pair <DFCoord, bool> foo;
std::stack < foo > flood; std::stack < foo > flood;
flood.push( foo(xy,false) ); flood.push( foo(xy,false) );
@ -500,8 +448,84 @@ command_result revflood(color_ostream &out, vector<string> & params)
flood.push(foo(DFCoord(current.x, current.y, current.z - 1), false)); flood.push(foo(DFCoord(current.x, current.y, current.z - 1), false));
} }
} }
}
// Lua entrypoint for unhideFlood_internal
static void unhideFlood(DFCoord pos)
{
CoreSuspender suspend;
MapCache MCache;
// no bounds checking needed for pos. if it's invalid, unhideFlood_internal
// will just exit immeditately
unhideFlood_internal(&MCache, pos);
MCache.WriteAll();
}
command_result revflood(color_ostream &out, vector<string> & 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(); MCache->WriteAll();
delete MCache; delete MCache;
return CR_OK; return CR_OK;
} }
@ -525,3 +549,8 @@ command_result revforget(color_ostream &out, vector<string> & params)
con.print("Reveal data forgotten!\n"); con.print("Reveal data forgotten!\n");
return CR_OK; return CR_OK;
} }
DFHACK_PLUGIN_LUA_FUNCTIONS {
DFHACK_LUA_FUNCTION(unhideFlood),
DFHACK_LUA_END
};