Add a couple more building api functions.

develop
Alexander Gavrilov 2012-05-06 11:22:55 +04:00
parent 05e8083c84
commit b70130cf36
5 changed files with 140 additions and 22 deletions

@ -873,10 +873,16 @@ Buildings module
Returns *width, height, centerx, centery*.
* ``dfhack.buildings.findAtTile(pos)``
* ``dfhack.buildings.findAtTile(pos)``, or ``findAtTile(x,y,z)``
Scans the buildings for the one located at the given tile.
Does not work on civzones. Warning: linear scan.
Does not work on civzones. Warning: linear scan if the map
tile indicates there are buildings at it.
* ``dfhack.buildings.findCivzonesAt(pos)``, or ``findCivzonesAt(x,y,z)``
Scans civzones, and returns a lua sequence of those that touch
the given tile, or *nil* if none.
* ``dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)``
@ -894,6 +900,10 @@ Buildings module
Returns the number of tiles included by extents, or defval.
* ``dfhack.buildings.containsTile(building, x, y[, room])``
Checks if the building contains the specified tile, either directly, or as room.
* ``dfhack.buildings.hasSupport(pos,size)``
Checks if a bridge constructed at specified position would have
@ -911,7 +921,7 @@ Low-level building creation functions;
Configures an object returned by ``allocInstance``, using specified
parameters wherever appropriate. If the building has fixed size along
any dimension, the corresponding input parameter will be ignored.
Returns *nil* if the building cannot be placed, or *true, width,
Returns *false* if the building cannot be placed, or *true, width,
height, rect_area, true_area*. Returned width and height are the
final values used by the building; true_area is less than rect_area
if any tiles were removed from designation.

@ -1081,9 +1081,14 @@ 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>
<li><p class="first"><tt class="docutils literal">dfhack.buildings.findAtTile(pos)</tt>, or <tt class="docutils literal">findAtTile(x,y,z)</tt></p>
<p>Scans the buildings for the one located at the given tile.
Does not work on civzones. Warning: linear scan.</p>
Does not work on civzones. Warning: linear scan if the map
tile indicates there are buildings at it.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.buildings.findCivzonesAt(pos)</tt>, or <tt class="docutils literal">findCivzonesAt(x,y,z)</tt></p>
<p>Scans civzones, and returns a lua sequence of those that touch
the given tile, or <em>nil</em> if none.</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,
@ -1098,6 +1103,9 @@ are removed from extents. If <tt class="docutils literal">allow_occupied</tt>, t
<li><p class="first"><tt class="docutils literal">dfhack.buildings.countExtentTiles(extents,defval)</tt></p>
<p>Returns the number of tiles included by extents, or defval.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.buildings.containsTile(building, x, y[, room])</tt></p>
<p>Checks if the building contains the specified tile, either directly, or as room.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.buildings.hasSupport(pos,size)</tt></p>
<p>Checks if a bridge constructed at specified position would have
support from terrain, and thus won't collapse if retracted.</p>
@ -1113,7 +1121,7 @@ at specified position. Returns the object, or <em>nil</em> in case of an error.<
<p>Configures an object returned by <tt class="docutils literal">allocInstance</tt>, using specified
parameters wherever appropriate. If the building has fixed size along
any dimension, the corresponding input parameter will be ignored.
Returns <em>nil</em> if the building cannot be placed, or <em>true, width,
Returns <em>false</em> if the building cannot be placed, or <em>true, width,
height, rect_area, true_area</em>. Returned width and height are the
final values used by the building; true_area is less than rect_area
if any tiles were removed from designation.</p>

@ -74,6 +74,7 @@ distribution.
#include "df/dfhack_material_category.h"
#include "df/job_material_category.h"
#include "df/burrow.h"
#include "df/building_civzonest.h"
#include <lua.h>
#include <lauxlib.h>
@ -109,6 +110,37 @@ int Lua::PushPosXYZ(lua_State *state, df::coord pos)
}
}
static df::coord2d CheckCoordXY(lua_State *state, int base, bool vararg = false)
{
df::coord2d p;
if (vararg && lua_gettop(state) <= base)
Lua::CheckDFAssign(state, &p, base);
else
{
p = df::coord2d(
luaL_checkint(state, base),
luaL_checkint(state, base+1)
);
}
return p;
}
static df::coord CheckCoordXYZ(lua_State *state, int base, bool vararg = false)
{
df::coord p;
if (vararg && lua_gettop(state) <= base)
Lua::CheckDFAssign(state, &p, base);
else
{
p = df::coord(
luaL_checkint(state, base),
luaL_checkint(state, base+1),
luaL_checkint(state, base+2)
);
}
return p;
}
/**************************************************
* Per-world persistent configuration storage API *
**************************************************/
@ -729,20 +761,8 @@ static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
static int maps_getTileBlock(lua_State *L)
{
df::map_block *block;
if (lua_gettop(L) == 1)
{
df::coord pos;
Lua::CheckDFAssign(L, &pos, 1);
block = Maps::getTileBlock(pos);
}
else
{
block = Maps::getTileBlock(
luaL_checkint(L, 1), luaL_checkint(L, 2), luaL_checkint(L, 3)
);
}
Lua::PushDFObject(L, block);
auto pos = CheckCoordXYZ(L, 1, true);
Lua::PushDFObject(L, Maps::getTileBlock(pos));
return 1;
}
@ -791,17 +811,39 @@ static const luaL_Reg dfhack_burrows_funcs[] = {
/***** Buildings module *****/
static bool buildings_containsTile(df::building *bld, int x, int y, bool room) {
return Buildings::containsTile(bld, df::coord2d(x,y), room);
}
static const LuaWrapper::FunctionReg dfhack_buildings_module[] = {
WRAPM(Buildings, findAtTile),
WRAPM(Buildings, allocInstance),
WRAPM(Buildings, checkFreeTiles),
WRAPM(Buildings, countExtentTiles),
WRAPN(containsTile, buildings_containsTile),
WRAPM(Buildings, hasSupport),
WRAPM(Buildings, constructWithItems),
WRAPM(Buildings, constructWithFilters),
{ NULL, NULL }
};
static int buildings_findAtTile(lua_State *L)
{
auto pos = CheckCoordXYZ(L, 1, true);
Lua::PushDFObject(L, Buildings::findAtTile(pos));
return 1;
}
static int buildings_findCivzonesAt(lua_State *L)
{
auto pos = CheckCoordXYZ(L, 1, true);
std::vector<df::building_civzonest*> pvec;
if (Buildings::findCivzonesAt(&pvec, pos))
Lua::PushVector(L, pvec);
else
lua_pushnil(L);
return 1;
}
static int buildings_getCorrectSize(lua_State *state)
{
df::coord2d size(luaL_optint(state, 1, 1), luaL_optint(state, 2, 1));
@ -844,6 +886,8 @@ static int buildings_setSize(lua_State *state)
}
static const luaL_Reg dfhack_buildings_funcs[] = {
{ "findAtTile", buildings_findAtTile },
{ "findCivzonesAt", buildings_findCivzonesAt },
{ "getCorrectSize", buildings_getCorrectSize },
{ "setSize", buildings_setSize },
{ NULL, NULL }

@ -39,6 +39,7 @@ namespace df
struct job_item;
struct item;
struct building_extents;
struct building_civzonest;
}
namespace DFHack
@ -91,12 +92,17 @@ 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);
/**
* Find civzones located at the specified tile.
*/
DFHACK_EXPORT bool findCivzonesAt(std::vector<df::building_civzonest*> *pvec, df::coord pos);
/**
* Allocates a building object using this type and position.
*/
@ -122,6 +128,11 @@ DFHACK_EXPORT bool checkFreeTiles(df::coord pos, df::coord2d size,
*/
DFHACK_EXPORT int countExtentTiles(df::building_extents *ext, int defval = -1);
/**
* Checks if the building contains the specified tile.
*/
DFHACK_EXPORT bool containsTile(df::building *bld, df::coord2d tile, bool room = false);
/**
* Checks if the area has support from the terrain.
*/

@ -58,6 +58,7 @@ using namespace DFHack;
#include "df/building_trapst.h"
#include "df/building_bridgest.h"
#include "df/building_coffinst.h"
#include "df/building_civzonest.h"
#include "df/building_furnacest.h"
#include "df/building_workshopst.h"
#include "df/building_screw_pumpst.h"
@ -153,6 +154,25 @@ df::building *Buildings::findAtTile(df::coord pos)
return NULL;
}
bool Buildings::findCivzonesAt(std::vector<df::building_civzonest*> *pvec, df::coord pos)
{
pvec->clear();
auto &vec = world->buildings.other[buildings_other_id::ANY_ZONE];
for (size_t i = 0; i < vec.size(); i++)
{
auto bld = strict_virtual_cast<df::building_civzonest>(vec[i]);
if (!bld || bld->z != pos.z || !containsTile(bld, pos))
continue;
pvec->push_back(bld);
}
return !pvec->empty();
}
df::building *Buildings::allocInstance(df::coord pos, df::building_type type, int subtype, int custom)
{
if (!building_next_id)
@ -464,6 +484,31 @@ int Buildings::countExtentTiles(df::building_extents *ext, int defval)
return cnt;
}
bool Buildings::containsTile(df::building *bld, df::coord2d tile, bool room)
{
CHECK_NULL_POINTER(bld);
if (room)
{
if (!bld->is_room || !bld->room.extents)
return false;
}
else
{
if (tile.x < bld->x1 || tile.x > bld->x2 || tile.y < bld->y1 || tile.y >= bld->y2)
return false;
}
if (bld->room.extents && (room || bld->isExtentShaped()))
{
uint8_t *etile = getExtentTile(bld->room, tile);
if (!etile || !*etile)
return false;
}
return true;
}
bool Buildings::hasSupport(df::coord pos, df::coord2d size)
{
for (int dx = -1; dx <= size.x; dx++)