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*. 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. 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)`` * ``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. 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)`` * ``dfhack.buildings.hasSupport(pos,size)``
Checks if a bridge constructed at specified position would have 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 Configures an object returned by ``allocInstance``, using specified
parameters wherever appropriate. If the building has fixed size along parameters wherever appropriate. If the building has fixed size along
any dimension, the corresponding input parameter will be ignored. 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 height, rect_area, true_area*. Returned width and height are the
final values used by the building; true_area is less than rect_area final values used by the building; true_area is less than rect_area
if any tiles were removed from designation. 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> <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> <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. <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>
<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,
@ -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> <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> <p>Returns the number of tiles included by extents, or defval.</p>
</li> </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> <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 <p>Checks if a bridge constructed at specified position would have
support from terrain, and thus won't collapse if retracted.</p> 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 <p>Configures an object returned by <tt class="docutils literal">allocInstance</tt>, using specified
parameters wherever appropriate. If the building has fixed size along parameters wherever appropriate. If the building has fixed size along
any dimension, the corresponding input parameter will be ignored. 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 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 final values used by the building; true_area is less than rect_area
if any tiles were removed from designation.</p> if any tiles were removed from designation.</p>

@ -74,6 +74,7 @@ distribution.
#include "df/dfhack_material_category.h" #include "df/dfhack_material_category.h"
#include "df/job_material_category.h" #include "df/job_material_category.h"
#include "df/burrow.h" #include "df/burrow.h"
#include "df/building_civzonest.h"
#include <lua.h> #include <lua.h>
#include <lauxlib.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 * * Per-world persistent configuration storage API *
**************************************************/ **************************************************/
@ -729,20 +761,8 @@ static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
static int maps_getTileBlock(lua_State *L) static int maps_getTileBlock(lua_State *L)
{ {
df::map_block *block; auto pos = CheckCoordXYZ(L, 1, true);
if (lua_gettop(L) == 1) Lua::PushDFObject(L, Maps::getTileBlock(pos));
{
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);
return 1; return 1;
} }
@ -791,17 +811,39 @@ static const luaL_Reg dfhack_burrows_funcs[] = {
/***** Buildings module *****/ /***** 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[] = { 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),
WRAPN(containsTile, buildings_containsTile),
WRAPM(Buildings, hasSupport), WRAPM(Buildings, hasSupport),
WRAPM(Buildings, constructWithItems), WRAPM(Buildings, constructWithItems),
WRAPM(Buildings, constructWithFilters), WRAPM(Buildings, constructWithFilters),
{ NULL, NULL } { 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) static int buildings_getCorrectSize(lua_State *state)
{ {
df::coord2d size(luaL_optint(state, 1, 1), luaL_optint(state, 2, 1)); 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[] = { static const luaL_Reg dfhack_buildings_funcs[] = {
{ "findAtTile", buildings_findAtTile },
{ "findCivzonesAt", buildings_findCivzonesAt },
{ "getCorrectSize", buildings_getCorrectSize }, { "getCorrectSize", buildings_getCorrectSize },
{ "setSize", buildings_setSize }, { "setSize", buildings_setSize },
{ NULL, NULL } { NULL, NULL }

@ -39,6 +39,7 @@ namespace df
struct job_item; struct job_item;
struct item; struct item;
struct building_extents; struct building_extents;
struct building_civzonest;
} }
namespace DFHack 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); DFHACK_EXPORT bool ReadCustomWorkshopTypes(std::map <uint32_t, std::string> & btypes);
/* /**
* Find the building located at the specified tile. * Find the building located at the specified tile.
* Does not work on civzones. * Does not work on civzones.
*/ */
DFHACK_EXPORT df::building *findAtTile(df::coord pos); 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. * 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); 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. * Checks if the area has support from the terrain.
*/ */

@ -58,6 +58,7 @@ using namespace DFHack;
#include "df/building_trapst.h" #include "df/building_trapst.h"
#include "df/building_bridgest.h" #include "df/building_bridgest.h"
#include "df/building_coffinst.h" #include "df/building_coffinst.h"
#include "df/building_civzonest.h"
#include "df/building_furnacest.h" #include "df/building_furnacest.h"
#include "df/building_workshopst.h" #include "df/building_workshopst.h"
#include "df/building_screw_pumpst.h" #include "df/building_screw_pumpst.h"
@ -153,6 +154,25 @@ df::building *Buildings::findAtTile(df::coord pos)
return NULL; 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) df::building *Buildings::allocInstance(df::coord pos, df::building_type type, int subtype, int custom)
{ {
if (!building_next_id) if (!building_next_id)
@ -464,6 +484,31 @@ int Buildings::countExtentTiles(df::building_extents *ext, int defval)
return cnt; 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) bool Buildings::hasSupport(df::coord pos, df::coord2d size)
{ {
for (int dx = -1; dx <= size.x; dx++) for (int dx = -1; dx <= size.x; dx++)