Skip to content

Commit 4cffb64

Browse files
committed
Update building creation code with new knowledge, and fix zone.
Also, document new lua api, and add a more convenient wrapper.
1 parent 2303a25 commit 4cffb64

10 files changed

Lines changed: 404 additions & 65 deletions

File tree

LUA_API.rst

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,70 @@ Burrows module
850850
Adds or removes the tile from the burrow. Returns *false* if invalid coords.
851851

852852

853+
Buildings module
854+
----------------
855+
856+
* ``dfhack.buildings.getSize(building)``
857+
858+
Returns *width, height, centerx, centery*.
859+
860+
* ``dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)``
861+
862+
Computes correct dimensions for the specified building type and orientation,
863+
using width and height for flexible dimensions.
864+
Returns *is_flexible, width, height, center_x, center_y*.
865+
866+
* ``dfhack.buildings.checkFreeTiles(pos,size[,extents,change_extents,allow_occupied])``
867+
868+
Checks if the rectangle defined by ``pos`` and ``size``, and possibly extents,
869+
can be used for placing a building. If ``change_extents`` is true, bad tiles
870+
are removed from extents. If ``allow_occupied``, the occupancy test is skipped.
871+
872+
* ``dfhack.buildings.countExtentTiles(extents,defval)``
873+
874+
Returns the number of tiles included by extents, or defval.
875+
876+
* ``dfhack.buildings.hasSupport(pos,size)``
877+
878+
Checks if a bridge constructed at specified position would have
879+
support from terrain, and thus won't collapse if retracted.
880+
881+
Low-level building creation functions;
882+
883+
* ``dfhack.buildings.allocInstance(pos, type, subtype, custom)``
884+
885+
Creates a new building instance of given type, subtype and custom type,
886+
at specified position. Returns the object, or *nil* in case of an error.
887+
888+
* ``dfhack.buildings.setSize(building, width, height, direction)``
889+
890+
Configures an object returned by ``allocInstance``, using specified
891+
parameters wherever appropriate. If the building has fixed size along
892+
any dimension, the corresponding input parameter will be ignored.
893+
Returns *nil* if the building cannot be placed, or *true, width,
894+
height, rect_area, true_area*. Returned width and height are the
895+
final values used by the building; true_area is less than rect_area
896+
if any tiles were removed from designation.
897+
898+
* ``dfhack.buildings.constructWithItems(building, items)``
899+
900+
Links a fully configured object created by ``allocInstance`` into the
901+
world for construction, using a list of specific items as material.
902+
Returns *true*, or *false* if impossible.
903+
904+
* ``dfhack.buildings.constructWithFilters(building, job_items)``
905+
906+
Links a fully configured object created by ``allocInstance`` into the
907+
world for construction, using a list of job_item filters as inputs.
908+
Returns *true*, or *false* if impossible. Filter objects are claimed
909+
and possibly destroyed in any case.
910+
Use a negative ``quantity`` field value to auto-compute the amount
911+
from the size of the building.
912+
913+
More high-level functions are implemented in lua and can be loaded by
914+
``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``.
915+
916+
853917
Core interpreter context
854918
========================
855919

Lua API.html

Lines changed: 67 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -343,17 +343,18 @@ <h1 class="title">DFHack Lua API</h1>
343343
<li><a class="reference internal" href="#items-module" id="id17">Items module</a></li>
344344
<li><a class="reference internal" href="#maps-module" id="id18">Maps module</a></li>
345345
<li><a class="reference internal" href="#burrows-module" id="id19">Burrows module</a></li>
346+
<li><a class="reference internal" href="#buildings-module" id="id20">Buildings module</a></li>
346347
</ul>
347348
</li>
348-
<li><a class="reference internal" href="#core-interpreter-context" id="id20">Core interpreter context</a><ul>
349-
<li><a class="reference internal" href="#event-type" id="id21">Event type</a></li>
349+
<li><a class="reference internal" href="#core-interpreter-context" id="id21">Core interpreter context</a><ul>
350+
<li><a class="reference internal" href="#event-type" id="id22">Event type</a></li>
350351
</ul>
351352
</li>
352353
</ul>
353354
</li>
354-
<li><a class="reference internal" href="#plugins" id="id22">Plugins</a><ul>
355-
<li><a class="reference internal" href="#burrows" id="id23">burrows</a></li>
356-
<li><a class="reference internal" href="#sort" id="id24">sort</a></li>
355+
<li><a class="reference internal" href="#plugins" id="id23">Plugins</a><ul>
356+
<li><a class="reference internal" href="#burrows" id="id24">burrows</a></li>
357+
<li><a class="reference internal" href="#sort" id="id25">sort</a></li>
357358
</ul>
358359
</li>
359360
</ul>
@@ -1061,9 +1062,65 @@ <h3><a class="toc-backref" href="#id19">Burrows module</a></h3>
10611062
</li>
10621063
</ul>
10631064
</div>
1065+
<div class="section" id="buildings-module">
1066+
<h3><a class="toc-backref" href="#id20">Buildings module</a></h3>
1067+
<ul>
1068+
<li><p class="first"><tt class="docutils literal">dfhack.buildings.getSize(building)</tt></p>
1069+
<p>Returns <em>width, height, centerx, centery</em>.</p>
1070+
</li>
1071+
<li><p class="first"><tt class="docutils literal">dfhack.buildings.getCorrectSize(width, height, type, subtype, custom, direction)</tt></p>
1072+
<p>Computes correct dimensions for the specified building type and orientation,
1073+
using width and height for flexible dimensions.
1074+
Returns <em>is_flexible, width, height, center_x, center_y</em>.</p>
1075+
</li>
1076+
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.buildings.checkFreeTiles(pos,size[,extents,change_extents,allow_occupied])</span></tt></p>
1077+
<p>Checks if the rectangle defined by <tt class="docutils literal">pos</tt> and <tt class="docutils literal">size</tt>, and possibly extents,
1078+
can be used for placing a building. If <tt class="docutils literal">change_extents</tt> is true, bad tiles
1079+
are removed from extents. If <tt class="docutils literal">allow_occupied</tt>, the occupancy test is skipped.</p>
1080+
</li>
1081+
<li><p class="first"><tt class="docutils literal">dfhack.buildings.countExtentTiles(extents,defval)</tt></p>
1082+
<p>Returns the number of tiles included by extents, or defval.</p>
1083+
</li>
1084+
<li><p class="first"><tt class="docutils literal">dfhack.buildings.hasSupport(pos,size)</tt></p>
1085+
<p>Checks if a bridge constructed at specified position would have
1086+
support from terrain, and thus won't collapse if retracted.</p>
1087+
</li>
1088+
</ul>
1089+
<p>Low-level building creation functions;</p>
1090+
<ul>
1091+
<li><p class="first"><tt class="docutils literal">dfhack.buildings.allocInstance(pos, type, subtype, custom)</tt></p>
1092+
<p>Creates a new building instance of given type, subtype and custom type,
1093+
at specified position. Returns the object, or <em>nil</em> in case of an error.</p>
1094+
</li>
1095+
<li><p class="first"><tt class="docutils literal">dfhack.buildings.setSize(building, width, height, direction)</tt></p>
1096+
<p>Configures an object returned by <tt class="docutils literal">allocInstance</tt>, using specified
1097+
parameters wherever appropriate. If the building has fixed size along
1098+
any dimension, the corresponding input parameter will be ignored.
1099+
Returns <em>nil</em> if the building cannot be placed, or <em>true, width,
1100+
height, rect_area, true_area</em>. Returned width and height are the
1101+
final values used by the building; true_area is less than rect_area
1102+
if any tiles were removed from designation.</p>
1103+
</li>
1104+
<li><p class="first"><tt class="docutils literal">dfhack.buildings.constructWithItems(building, items)</tt></p>
1105+
<p>Links a fully configured object created by <tt class="docutils literal">allocInstance</tt> into the
1106+
world for construction, using a list of specific items as material.
1107+
Returns <em>true</em>, or <em>false</em> if impossible.</p>
1108+
</li>
1109+
<li><p class="first"><tt class="docutils literal">dfhack.buildings.constructWithFilters(building, job_items)</tt></p>
1110+
<p>Links a fully configured object created by <tt class="docutils literal">allocInstance</tt> into the
1111+
world for construction, using a list of job_item filters as inputs.
1112+
Returns <em>true</em>, or <em>false</em> if impossible. Filter objects are claimed
1113+
and possibly destroyed in any case.
1114+
Use a negative <tt class="docutils literal">quantity</tt> field value to auto-compute the amount
1115+
from the size of the building.</p>
1116+
</li>
1117+
</ul>
1118+
<p>More high-level functions are implemented in lua and can be loaded by
1119+
<tt class="docutils literal"><span class="pre">require('dfhack.buildings')</span></tt>. See <tt class="docutils literal">hack/lua/dfhack/buildings.lua</tt>.</p>
1120+
</div>
10641121
</div>
10651122
<div class="section" id="core-interpreter-context">
1066-
<h2><a class="toc-backref" href="#id20">Core interpreter context</a></h2>
1123+
<h2><a class="toc-backref" href="#id21">Core interpreter context</a></h2>
10671124
<p>While plugins can create any number of interpreter instances,
10681125
there is one special context managed by dfhack core. It is the
10691126
only context that can receive events from DF and plugins.</p>
@@ -1077,7 +1134,7 @@ <h2><a class="toc-backref" href="#id20">Core interpreter context</a></h2>
10771134
</li>
10781135
</ul>
10791136
<div class="section" id="event-type">
1080-
<h3><a class="toc-backref" href="#id21">Event type</a></h3>
1137+
<h3><a class="toc-backref" href="#id22">Event type</a></h3>
10811138
<p>An event is just a lua table with a predefined metatable that
10821139
contains a __call metamethod. When it is invoked, it loops
10831140
through the table with next and calls all contained values.
@@ -1103,14 +1160,14 @@ <h3><a class="toc-backref" href="#id21">Event type</a></h3>
11031160
</div>
11041161
</div>
11051162
<div class="section" id="plugins">
1106-
<h1><a class="toc-backref" href="#id22">Plugins</a></h1>
1163+
<h1><a class="toc-backref" href="#id23">Plugins</a></h1>
11071164
<p>DFHack plugins may export native functions and events
11081165
to lua contexts. They are automatically imported by
11091166
<tt class="docutils literal"><span class="pre">mkmodule('plugins.&lt;name&gt;')</span></tt>; this means that a lua
11101167
module file is still necessary for <tt class="docutils literal">require</tt> to read.</p>
11111168
<p>The following plugins have lua support.</p>
11121169
<div class="section" id="burrows">
1113-
<h2><a class="toc-backref" href="#id23">burrows</a></h2>
1170+
<h2><a class="toc-backref" href="#id24">burrows</a></h2>
11141171
<p>Implements extended burrow manipulations.</p>
11151172
<p>Events:</p>
11161173
<ul>
@@ -1148,7 +1205,7 @@ <h2><a class="toc-backref" href="#id23">burrows</a></h2>
11481205
<p>The lua module file also re-exports functions from <tt class="docutils literal">dfhack.burrows</tt>.</p>
11491206
</div>
11501207
<div class="section" id="sort">
1151-
<h2><a class="toc-backref" href="#id24">sort</a></h2>
1208+
<h2><a class="toc-backref" href="#id25">sort</a></h2>
11521209
<p>Does not export any native functions as of now. Instead, it
11531210
calls lua code to perform the actual ordering of list items.</p>
11541211
</div>

library/LuaApi.cpp

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -768,23 +768,25 @@ static const luaL_Reg dfhack_burrows_funcs[] = {
768768
static const LuaWrapper::FunctionReg dfhack_buildings_module[] = {
769769
WRAPM(Buildings, allocInstance),
770770
WRAPM(Buildings, checkFreeTiles),
771-
WRAPM(Buildings, setSize),
771+
WRAPM(Buildings, countExtentTiles),
772+
WRAPM(Buildings, hasSupport),
772773
WRAPM(Buildings, constructWithItems),
773774
WRAPM(Buildings, constructWithFilters),
774775
{ NULL, NULL }
775776
};
776777

777778
static int buildings_getCorrectSize(lua_State *state)
778779
{
779-
int w = luaL_optint(state, 1, 1);
780-
int h = luaL_optint(state, 2, 1);
781-
int t = luaL_optint(state, 3, -1);
780+
df::coord2d size(luaL_optint(state, 1, 1), luaL_optint(state, 2, 1));
781+
782+
auto t = (df::building_type)luaL_optint(state, 3, -1);
782783
int st = luaL_optint(state, 4, -1);
783784
int cu = luaL_optint(state, 5, -1);
784785
int d = luaL_optint(state, 6, 0);
785-
df::coord2d size(w,h);
786+
786787
df::coord2d center;
787-
bool flexible = Buildings::getCorrectSize(size, center, df::building_type(t), st, cu, d);
788+
bool flexible = Buildings::getCorrectSize(size, center, t, st, cu, d);
789+
788790
lua_pushboolean(state, flexible);
789791
lua_pushinteger(state, size.x);
790792
lua_pushinteger(state, size.y);
@@ -793,8 +795,30 @@ static int buildings_getCorrectSize(lua_State *state)
793795
return 5;
794796
}
795797

798+
static int buildings_setSize(lua_State *state)
799+
{
800+
auto bld = Lua::CheckDFObject<df::building>(state, 1);
801+
df::coord2d size(luaL_optint(state, 2, 1), luaL_optint(state, 3, 1));
802+
int dir = luaL_optint(state, 4, 0);
803+
bool ok = Buildings::setSize(bld, size, dir);
804+
lua_pushboolean(state, ok);
805+
if (ok)
806+
{
807+
auto size = Buildings::getSize(bld).second;
808+
int area = size.x*size.y;
809+
lua_pushinteger(state, size.x);
810+
lua_pushinteger(state, size.y);
811+
lua_pushinteger(state, area);
812+
lua_pushinteger(state, Buildings::countExtentTiles(&bld->room, area));
813+
return 5;
814+
}
815+
else
816+
return 1;
817+
}
818+
796819
static const luaL_Reg dfhack_buildings_funcs[] = {
797820
{ "getCorrectSize", buildings_getCorrectSize },
821+
{ "setSize", buildings_setSize },
798822
{ NULL, NULL }
799823
};
800824

library/include/modules/Buildings.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,30 @@ DFHACK_EXPORT bool getCorrectSize(df::coord2d &size, df::coord2d &center,
108108
* Checks if the tiles are free to be built upon.
109109
*/
110110
DFHACK_EXPORT bool checkFreeTiles(df::coord pos, df::coord2d size,
111-
df::building_extents *ext = NULL, bool create_ext = false);
111+
df::building_extents *ext = NULL,
112+
bool create_ext = false, bool allow_occupied = false);
113+
114+
/**
115+
* Returns the number of tiles included by the extent, or defval.
116+
*/
117+
DFHACK_EXPORT int countExtentTiles(df::building_extents *ext, int defval = -1);
118+
119+
/**
120+
* Checks if the area has support from the terrain.
121+
*/
122+
DFHACK_EXPORT bool hasSupport(df::coord pos, df::coord2d size);
112123

113124
/**
114125
* Sets the size of the building, using size and direction as guidance.
115126
* Returns true if the building can be created at its position, using that size.
116127
*/
117128
DFHACK_EXPORT bool setSize(df::building *bld, df::coord2d size, int direction = 0);
118129

130+
/**
131+
* Decodes the size of the building into pos and size.
132+
*/
133+
DFHACK_EXPORT std::pair<df::coord,df::coord2d> getSize(df::building *bld);
134+
119135
/**
120136
* Initiates construction of the building, using specified items as inputs.
121137
* Returns true if success.

library/lua/dfhack.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ function dfhack.maps.getTileSize()
173173
return map.x_count, map.y_count, map.z_count
174174
end
175175

176+
function dfhack.buildings.getSize(bld)
177+
local x, y = bld.x1, bld.y1
178+
return bld.x2+1-x, bld.y2+1-y, bld.centerx-x, bld.centery-y
179+
end
180+
176181
-- Interactive
177182

178183
local print_banner = true

0 commit comments

Comments
 (0)