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.
-
+
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.
@@ -1134,7 +1150,7 @@ only context that can receive events from DF and plugins.
-
+
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 dfhack.safecall.
-
+
DFHack plugins may export native functions and events
to lua contexts. They are automatically imported by
mkmodule('plugins.<name>'); this means that a lua
module file is still necessary for require to read.
The following plugins have lua support.
-
+
Implements extended burrow manipulations.
Events:
-
+
Does not export any native functions as of now. Instead, it
calls lua code to perform the actual ordering of list items.
diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp
index 11cf73c3f..0d0647183 100644
--- a/library/LuaApi.cpp
+++ b/library/LuaApi.cpp
@@ -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);
}
diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h
index 610688187..9e529b6ca 100644
--- a/library/include/modules/Buildings.h
+++ b/library/include/modules/Buildings.h
@@ -91,6 +91,12 @@ DFHACK_EXPORT bool Read (const uint32_t index, t_building & building);
*/
DFHACK_EXPORT bool ReadCustomWorkshopTypes(std::map
& 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.
*/
diff --git a/library/include/modules/Constructions.h b/library/include/modules/Constructions.h
index e76cc7ba1..17da12711 100644
--- a/library/include/modules/Constructions.h
+++ b/library/include/modules/Constructions.h
@@ -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
diff --git a/library/include/modules/Maps.h b/library/include/modules/Maps.h
index 332954cda..fc18ca7e1 100644
--- a/library/include/modules/Maps.h
+++ b/library/include/modules/Maps.h
@@ -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
diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp
index bc062f980..e587a4916 100644
--- a/library/modules/Buildings.cpp
+++ b/library/modules/Buildings.cpp
@@ -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 & 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 ¢er,
}
}
-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)
diff --git a/library/modules/Constructions.cpp b/library/modules/Constructions.cpp
index 4c2bf8ec1..a38048391 100644
--- a/library/modules/Constructions.cpp
+++ b/library/modules/Constructions.cpp
@@ -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(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(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 filters;
+ filters.push_back(filter);
+
+ if (!Buildings::constructWithFilters(newinst, filters))
+ {
+ delete newinst;
+ return false;
+ }
+
+ return true;
+}
+
diff --git a/library/modules/Maps.cpp b/library/modules/Maps.cpp
index ddf5d5069..69f591a0f 100644
--- a/library/modules/Maps.cpp
+++ b/library/modules/Maps.cpp
@@ -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;