Add a convenience function for designating constructions.

develop
Alexander Gavrilov 2012-05-01 19:55:25 +04:00
parent 4cffb6428d
commit eadce95940
9 changed files with 194 additions and 21 deletions

@ -857,6 +857,11 @@ Buildings module
Returns *width, height, centerx, centery*. Returns *width, height, centerx, centery*.
* ``dfhack.buildings.findAtTile(pos)``
Scans the buildings for the one located at the given tile.
Does not work on civzones. Warning: linear scan.
* ``dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)`` * ``dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)``
Computes correct dimensions for the specified building type and orientation, Computes correct dimensions for the specified building type and orientation,
@ -913,6 +918,16 @@ Low-level building creation functions;
More high-level functions are implemented in lua and can be loaded by More high-level functions are implemented in lua and can be loaded by
``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``. ``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``.
Constructions module
--------------------
* ``dfhack.constructions.designateNew(pos,type,item_type,mat_index)``
Designates a new construction at given position. If there already is
a planned but not completed construction there, changes its type.
Returns *true*, or *false* if obstructed.
Note that designated constructions are technically buildings.
Core interpreter context Core interpreter context
======================== ========================

@ -344,17 +344,18 @@ ul.auto-toc {
<li><a class="reference internal" href="#maps-module" id="id18">Maps module</a></li> <li><a class="reference internal" href="#maps-module" id="id18">Maps module</a></li>
<li><a class="reference internal" href="#burrows-module" id="id19">Burrows module</a></li> <li><a class="reference internal" href="#burrows-module" id="id19">Burrows module</a></li>
<li><a class="reference internal" href="#buildings-module" id="id20">Buildings module</a></li> <li><a class="reference internal" href="#buildings-module" id="id20">Buildings module</a></li>
<li><a class="reference internal" href="#constructions-module" id="id21">Constructions module</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#core-interpreter-context" id="id21">Core interpreter context</a><ul> <li><a class="reference internal" href="#core-interpreter-context" id="id22">Core interpreter context</a><ul>
<li><a class="reference internal" href="#event-type" id="id22">Event type</a></li> <li><a class="reference internal" href="#event-type" id="id23">Event type</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
</li> </li>
<li><a class="reference internal" href="#plugins" id="id23">Plugins</a><ul> <li><a class="reference internal" href="#plugins" id="id24">Plugins</a><ul>
<li><a class="reference internal" href="#burrows" id="id24">burrows</a></li> <li><a class="reference internal" href="#burrows" id="id25">burrows</a></li>
<li><a class="reference internal" href="#sort" id="id25">sort</a></li> <li><a class="reference internal" href="#sort" id="id26">sort</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>
@ -1068,6 +1069,10 @@ burrows, or the presence of invaders.</p>
<li><p class="first"><tt class="docutils literal">dfhack.buildings.getSize(building)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.buildings.getSize(building)</tt></p>
<p>Returns <em>width, height, centerx, centery</em>.</p> <p>Returns <em>width, height, centerx, centery</em>.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.buildings.findAtTile(pos)</tt></p>
<p>Scans the buildings for the one located at the given tile.
Does not work on civzones. Warning: linear scan.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)</tt></p>
<p>Computes correct dimensions for the specified building type and orientation, <p>Computes correct dimensions for the specified building type and orientation,
using width and height for flexible dimensions. using width and height for flexible dimensions.
@ -1118,9 +1123,20 @@ from the size of the building.</p>
<p>More high-level functions are implemented in lua and can be loaded by <p>More high-level functions are implemented in lua and can be loaded by
<tt class="docutils literal"><span class="pre">require('dfhack.buildings')</span></tt>. See <tt class="docutils literal">hack/lua/dfhack/buildings.lua</tt>.</p> <tt class="docutils literal"><span class="pre">require('dfhack.buildings')</span></tt>. See <tt class="docutils literal">hack/lua/dfhack/buildings.lua</tt>.</p>
</div> </div>
<div class="section" id="constructions-module">
<h3><a class="toc-backref" href="#id21">Constructions module</a></h3>
<ul>
<li><p class="first"><tt class="docutils literal">dfhack.constructions.designateNew(pos,type,item_type,mat_index)</tt></p>
<p>Designates a new construction at given position. If there already is
a planned but not completed construction there, changes its type.
Returns <em>true</em> or <em>false</em> if obstructed.
Note that designated constructions are technically buildings.</p>
</li>
</ul>
</div>
</div> </div>
<div class="section" id="core-interpreter-context"> <div class="section" id="core-interpreter-context">
<h2><a class="toc-backref" href="#id21">Core interpreter context</a></h2> <h2><a class="toc-backref" href="#id22">Core interpreter context</a></h2>
<p>While plugins can create any number of interpreter instances, <p>While plugins can create any number of interpreter instances,
there is one special context managed by dfhack core. It is the there is one special context managed by dfhack core. It is the
only context that can receive events from DF and plugins.</p> only context that can receive events from DF and plugins.</p>
@ -1134,7 +1150,7 @@ only context that can receive events from DF and plugins.</p>
</li> </li>
</ul> </ul>
<div class="section" id="event-type"> <div class="section" id="event-type">
<h3><a class="toc-backref" href="#id22">Event type</a></h3> <h3><a class="toc-backref" href="#id23">Event type</a></h3>
<p>An event is just a lua table with a predefined metatable that <p>An event is just a lua table with a predefined metatable that
contains a __call metamethod. When it is invoked, it loops contains a __call metamethod. When it is invoked, it loops
through the table with next and calls all contained values. through the table with next and calls all contained values.
@ -1160,14 +1176,14 @@ order using <tt class="docutils literal">dfhack.safecall</tt>.</p>
</div> </div>
</div> </div>
<div class="section" id="plugins"> <div class="section" id="plugins">
<h1><a class="toc-backref" href="#id23">Plugins</a></h1> <h1><a class="toc-backref" href="#id24">Plugins</a></h1>
<p>DFHack plugins may export native functions and events <p>DFHack plugins may export native functions and events
to lua contexts. They are automatically imported by to lua contexts. They are automatically imported by
<tt class="docutils literal"><span class="pre">mkmodule('plugins.&lt;name&gt;')</span></tt>; this means that a lua <tt class="docutils literal"><span class="pre">mkmodule('plugins.&lt;name&gt;')</span></tt>; this means that a lua
module file is still necessary for <tt class="docutils literal">require</tt> to read.</p> module file is still necessary for <tt class="docutils literal">require</tt> to read.</p>
<p>The following plugins have lua support.</p> <p>The following plugins have lua support.</p>
<div class="section" id="burrows"> <div class="section" id="burrows">
<h2><a class="toc-backref" href="#id24">burrows</a></h2> <h2><a class="toc-backref" href="#id25">burrows</a></h2>
<p>Implements extended burrow manipulations.</p> <p>Implements extended burrow manipulations.</p>
<p>Events:</p> <p>Events:</p>
<ul> <ul>
@ -1205,7 +1221,7 @@ set is the same as used by the command line.</p>
<p>The lua module file also re-exports functions from <tt class="docutils literal">dfhack.burrows</tt>.</p> <p>The lua module file also re-exports functions from <tt class="docutils literal">dfhack.burrows</tt>.</p>
</div> </div>
<div class="section" id="sort"> <div class="section" id="sort">
<h2><a class="toc-backref" href="#id25">sort</a></h2> <h2><a class="toc-backref" href="#id26">sort</a></h2>
<p>Does not export any native functions as of now. Instead, it <p>Does not export any native functions as of now. Instead, it
calls lua code to perform the actual ordering of list items.</p> calls lua code to perform the actual ordering of list items.</p>
</div> </div>

@ -48,6 +48,7 @@ distribution.
#include "modules/MapCache.h" #include "modules/MapCache.h"
#include "modules/Burrows.h" #include "modules/Burrows.h"
#include "modules/Buildings.h" #include "modules/Buildings.h"
#include "modules/Constructions.h"
#include "LuaWrapper.h" #include "LuaWrapper.h"
#include "LuaTools.h" #include "LuaTools.h"
@ -766,6 +767,7 @@ static const luaL_Reg dfhack_burrows_funcs[] = {
/***** Buildings module *****/ /***** Buildings module *****/
static const LuaWrapper::FunctionReg dfhack_buildings_module[] = { static const LuaWrapper::FunctionReg dfhack_buildings_module[] = {
WRAPM(Buildings, findAtTile),
WRAPM(Buildings, allocInstance), WRAPM(Buildings, allocInstance),
WRAPM(Buildings, checkFreeTiles), WRAPM(Buildings, checkFreeTiles),
WRAPM(Buildings, countExtentTiles), WRAPM(Buildings, countExtentTiles),
@ -822,6 +824,14 @@ static const luaL_Reg dfhack_buildings_funcs[] = {
{ NULL, NULL } { NULL, NULL }
}; };
/***** Constructions module *****/
static const LuaWrapper::FunctionReg dfhack_constructions_module[] = {
WRAPM(Constructions, designateNew),
{ NULL, NULL }
};
/************************ /************************
* Main Open function * * Main Open function *
************************/ ************************/
@ -839,4 +849,5 @@ void OpenDFHackApi(lua_State *state)
OpenModule(state, "maps", dfhack_maps_module, dfhack_maps_funcs); OpenModule(state, "maps", dfhack_maps_module, dfhack_maps_funcs);
OpenModule(state, "burrows", dfhack_burrows_module, dfhack_burrows_funcs); OpenModule(state, "burrows", dfhack_burrows_module, dfhack_burrows_funcs);
OpenModule(state, "buildings", dfhack_buildings_module, dfhack_buildings_funcs); OpenModule(state, "buildings", dfhack_buildings_module, dfhack_buildings_funcs);
OpenModule(state, "constructions", dfhack_constructions_module);
} }

@ -91,6 +91,12 @@ DFHACK_EXPORT bool Read (const uint32_t index, t_building & building);
*/ */
DFHACK_EXPORT bool ReadCustomWorkshopTypes(std::map <uint32_t, std::string> & btypes); DFHACK_EXPORT bool ReadCustomWorkshopTypes(std::map <uint32_t, std::string> & btypes);
/*
* Find the building located at the specified tile.
* Does not work on civzones.
*/
DFHACK_EXPORT df::building *findAtTile(df::coord pos);
/** /**
* Allocates a building object using this type and position. * Allocates a building object using this type and position.
*/ */

@ -31,6 +31,8 @@ distribution.
#include "Export.h" #include "Export.h"
#include "DataDefs.h" #include "DataDefs.h"
#include "df/construction.h" #include "df/construction.h"
#include "df/construction_type.h"
#include "df/item_type.h"
/** /**
* \defgroup grp_constructions Construction module parts * \defgroup grp_constructions Construction module parts
@ -57,6 +59,9 @@ DFHACK_EXPORT bool isValid();
DFHACK_EXPORT uint32_t getCount(); DFHACK_EXPORT uint32_t getCount();
DFHACK_EXPORT bool copyConstruction (const int32_t index, t_construction &out); DFHACK_EXPORT bool copyConstruction (const int32_t index, t_construction &out);
DFHACK_EXPORT df::construction * getConstruction (const int32_t index); DFHACK_EXPORT df::construction * getConstruction (const int32_t index);
DFHACK_EXPORT bool designateNew(df::coord pos, df::construction_type type,
df::item_type item = df::item_type::NONE, int mat_index = -1);
} }
} }
#endif #endif

@ -241,6 +241,20 @@ extern DFHACK_EXPORT df::map_block * getTileBlock (int32_t x, int32_t y, int32_t
inline df::map_block * getBlock (df::coord pos) { return getBlock(pos.x, pos.y, pos.z); } inline df::map_block * getBlock (df::coord pos) { return getBlock(pos.x, pos.y, pos.z); }
inline df::map_block * getTileBlock (df::coord pos) { return getTileBlock(pos.x, pos.y, pos.z); } inline df::map_block * getTileBlock (df::coord pos) { return getTileBlock(pos.x, pos.y, pos.z); }
extern DFHACK_EXPORT df::tiletype *getTileType(int32_t x, int32_t y, int32_t z);
extern DFHACK_EXPORT df::tile_designation *getTileDesignation(int32_t x, int32_t y, int32_t z);
extern DFHACK_EXPORT df::tile_occupancy *getTileOccupancy(int32_t x, int32_t y, int32_t z);
inline df::tiletype *getTileType(df::coord pos) {
return getTileType(pos.x, pos.y, pos.z);
}
inline df::tile_designation *getTileDesignation(df::coord pos) {
return getTileDesignation(pos.x, pos.y, pos.z);
}
inline df::tile_occupancy *getTileOccupancy(df::coord pos) {
return getTileOccupancy(pos.x, pos.y, pos.z);
}
DFHACK_EXPORT df::world_data::T_region_map *getRegionBiome(df::coord2d rgn_pos); DFHACK_EXPORT df::world_data::T_region_map *getRegionBiome(df::coord2d rgn_pos);
/// sorts the block event vector into multiple vectors by type /// sorts the block event vector into multiple vectors by type

@ -72,6 +72,17 @@ using df::global::building_next_id;
using df::global::process_jobs; using df::global::process_jobs;
using df::building_def; using df::building_def;
static uint8_t *getExtentTile(df::building_extents &extent, df::coord2d tile)
{
if (!extent.extents)
return NULL;
int dx = tile.x - extent.x;
int dy = tile.y - extent.y;
if (dx < 0 || dy < 0 || dx >= extent.width || dy >= extent.height)
return NULL;
return &extent.extents[dx + dy*extent.width];
}
uint32_t Buildings::getNumBuildings() uint32_t Buildings::getNumBuildings()
{ {
return world->buildings.all.size(); return world->buildings.all.size();
@ -110,6 +121,38 @@ bool Buildings::ReadCustomWorkshopTypes(map <uint32_t, string> & btypes)
return true; return true;
} }
df::building *Buildings::findAtTile(df::coord pos)
{
auto occ = Maps::getTileOccupancy(pos);
if (!occ || !occ->bits.building)
return NULL;
auto &vec = df::building::get_vector();
for (size_t i = 0; i < vec.size(); i++)
{
auto bld = vec[i];
if (pos.z != bld->z ||
pos.x < bld->x1 || pos.x > bld->x2 ||
pos.y < bld->y1 || pos.y > bld->y2)
continue;
if (!bld->isSettingOccupancy())
continue;
if (bld->room.extents && bld->isExtentShaped())
{
auto etile = getExtentTile(bld->room, pos);
if (!etile || !*etile)
continue;
}
return bld;
}
return NULL;
}
df::building *Buildings::allocInstance(df::coord pos, df::building_type type, int subtype, int custom) df::building *Buildings::allocInstance(df::coord pos, df::building_type type, int subtype, int custom)
{ {
if (!building_next_id) if (!building_next_id)
@ -319,17 +362,6 @@ bool Buildings::getCorrectSize(df::coord2d &size, df::coord2d &center,
} }
} }
static uint8_t *getExtentTile(df::building_extents &extent, df::coord2d tile)
{
if (!extent.extents)
return NULL;
int dx = tile.x - extent.x;
int dy = tile.y - extent.y;
if (dx < 0 || dy < 0 || dx >= extent.width || dy >= extent.height)
return NULL;
return &extent.extents[dx + dy*extent.width];
}
bool Buildings::checkFreeTiles(df::coord pos, df::coord2d size, bool Buildings::checkFreeTiles(df::coord pos, df::coord2d size,
df::building_extents *ext, df::building_extents *ext,
bool create_ext, bool allow_occupied) bool create_ext, bool allow_occupied)

@ -35,9 +35,20 @@ using namespace std;
#include "MemAccess.h" #include "MemAccess.h"
#include "Types.h" #include "Types.h"
#include "Core.h" #include "Core.h"
#include "modules/Constructions.h" #include "modules/Constructions.h"
#include "modules/Buildings.h"
#include "modules/Maps.h"
#include "TileTypes.h"
#include "df/world.h" #include "df/world.h"
#include "df/job_item.h"
#include "df/building_type.h"
#include "df/building_constructionst.h"
using namespace DFHack; using namespace DFHack;
using namespace df::enums;
using df::global::world; using df::global::world;
bool Constructions::isValid() bool Constructions::isValid()
@ -73,3 +84,48 @@ bool Constructions::copyConstruction(const int32_t index, t_construction &out)
out.original_tile = out.origin->original_tile; out.original_tile = out.origin->original_tile;
return true; return true;
} }
bool Constructions::designateNew(df::coord pos, df::construction_type type,
df::item_type item, int mat_index)
{
auto ttype = Maps::getTileType(pos);
if (!ttype || tileMaterial(*ttype) == tiletype_material::CONSTRUCTION)
return false;
auto current = Buildings::findAtTile(pos);
if (current)
{
auto cons = strict_virtual_cast<df::building_constructionst>(current);
if (!cons)
return false;
cons->type = type;
return true;
}
auto newinst = Buildings::allocInstance(pos, building_type::Construction);
if (!newinst)
return false;
auto newcons = strict_virtual_cast<df::building_constructionst>(newinst);
newcons->type = type;
df::job_item *filter = new df::job_item();
filter->item_type = item;
filter->mat_index = mat_index;
filter->flags2.bits.building_material = true;
if (mat_index < 0)
filter->flags2.bits.non_economic = true;
std::vector<df::job_item*> filters;
filters.push_back(filter);
if (!Buildings::constructWithFilters(newinst, filters))
{
delete newinst;
return false;
}
return true;
}

@ -145,6 +145,24 @@ df::map_block *Maps::getTileBlock (int32_t x, int32_t y, int32_t z)
return world->map.block_index[x >> 4][y >> 4][z]; return world->map.block_index[x >> 4][y >> 4][z];
} }
df::tiletype *Maps::getTileType(int32_t x, int32_t y, int32_t z)
{
df::map_block *block = getTileBlock(x,y,z);
return block ? &block->tiletype[x&15][y&15] : NULL;
}
df::tile_designation *Maps::getTileDesignation(int32_t x, int32_t y, int32_t z)
{
df::map_block *block = getTileBlock(x,y,z);
return block ? &block->designation[x&15][y&15] : NULL;
}
df::tile_occupancy *Maps::getTileOccupancy(int32_t x, int32_t y, int32_t z)
{
df::map_block *block = getTileBlock(x,y,z);
return block ? &block->occupancy[x&15][y&15] : NULL;
}
df::world_data::T_region_map *Maps::getRegionBiome(df::coord2d rgn_pos) df::world_data::T_region_map *Maps::getRegionBiome(df::coord2d rgn_pos)
{ {
auto data = world->world_data; auto data = world->world_data;