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*.
* ``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)``
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
``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
========================

@ -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="#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="#constructions-module" id="id21">Constructions module</a></li>
</ul>
</li>
<li><a class="reference internal" href="#core-interpreter-context" id="id21">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="#core-interpreter-context" id="id22">Core interpreter context</a><ul>
<li><a class="reference internal" href="#event-type" id="id23">Event type</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#plugins" id="id23">Plugins</a><ul>
<li><a class="reference internal" href="#burrows" id="id24">burrows</a></li>
<li><a class="reference internal" href="#sort" id="id25">sort</a></li>
<li><a class="reference internal" href="#plugins" id="id24">Plugins</a><ul>
<li><a class="reference internal" href="#burrows" id="id25">burrows</a></li>
<li><a class="reference internal" href="#sort" id="id26">sort</a></li>
</ul>
</li>
</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>
<p>Returns <em>width, height, centerx, centery</em>.</p>
</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>
<p>Computes correct dimensions for the specified building type and orientation,
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
<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 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 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,
there is one special context managed by dfhack core. It is the
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>
</ul>
<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
contains a __call metamethod. When it is invoked, it loops
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 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
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
module file is still necessary for <tt class="docutils literal">require</tt> to read.</p>
<p>The following plugins have lua support.</p>
<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>Events:</p>
<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>
</div>
<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
calls lua code to perform the actual ordering of list items.</p>
</div>

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

@ -31,6 +31,8 @@ distribution.
#include "Export.h"
#include "DataDefs.h"
#include "df/construction.h"
#include "df/construction_type.h"
#include "df/item_type.h"
/**
* \defgroup grp_constructions Construction module parts
@ -57,6 +59,9 @@ DFHACK_EXPORT bool isValid();
DFHACK_EXPORT uint32_t getCount();
DFHACK_EXPORT bool copyConstruction (const int32_t index, t_construction &out);
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

@ -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 * 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);
/// 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::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()
{
return world->buildings.all.size();
@ -110,6 +121,38 @@ bool Buildings::ReadCustomWorkshopTypes(map <uint32_t, string> & btypes)
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)
{
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,
df::building_extents *ext,
bool create_ext, bool allow_occupied)

@ -35,9 +35,20 @@ using namespace std;
#include "MemAccess.h"
#include "Types.h"
#include "Core.h"
#include "modules/Constructions.h"
#include "modules/Buildings.h"
#include "modules/Maps.h"
#include "TileTypes.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 df::enums;
using df::global::world;
bool Constructions::isValid()
@ -73,3 +84,48 @@ bool Constructions::copyConstruction(const int32_t index, t_construction &out)
out.original_tile = out.origin->original_tile;
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];
}
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)
{
auto data = world->world_data;