Merge remote-tracking branch 'angavrilov/master'

develop
Kelly Martin 2012-05-14 07:09:54 -05:00
commit fabc6d95e6
10 changed files with 393 additions and 67 deletions

@ -807,7 +807,7 @@ Maps module
Returns a map block object for given df::coord or x,y,z in local tile coordinates. Returns a map block object for given df::coord or x,y,z in local tile coordinates.
* ``dfhack.maps.getRegionBiome(region_coord2d)`` * ``dfhack.maps.getRegionBiome(region_coord2d)``, or ``getRegionBiome(x,y)``
Returns the biome info struct for the given global map region. Returns the biome info struct for the given global map region.
@ -823,6 +823,10 @@ Maps module
Returns the local feature object with the given region coords and index. Returns the local feature object with the given region coords and index.
* ``dfhack.maps.getTileBiomeRgn(coords)``, or ``getTileBiomeRgn(x,y,z)``
Returns *x, y* for use with ``getRegionBiome``.
* ``dfhack.maps.canWalkBetween(pos1, pos2)`` * ``dfhack.maps.canWalkBetween(pos1, pos2)``
Checks if a dwarf may be able to walk between the two tiles, Checks if a dwarf may be able to walk between the two tiles,
@ -967,6 +971,80 @@ Low-level building creation functions;
More high-level functions are implemented in lua and can be loaded by More high-level functions are implemented in lua and can be loaded by
``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``. ``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``.
Among them are:
* ``dfhack.buildings.getFiltersByType(argtable,type,subtype,custom)``
Returns a sequence of lua structures, describing input item filters
suitable for the specified building type, or *nil* if unknown or invalid.
The returned sequence is suitable for use as the ``job_items`` argument
of ``constructWithFilters``.
Uses tables defined in ``buildings.lua``.
Argtable members ``material`` (the default name), ``bucket``, ``barrel``,
``chain``, ``mechanism``, ``screw``, ``pipe``, ``anvil``, ``weapon`` are used to
augment the basic attributes with more detailed information if the
building has input items with the matching name (see the tables for naming details).
Note that it is impossible to *override* any properties this way, only supply those that
are not mentioned otherwise; one exception is that flags2.non_economic
is automatically cleared if an explicit material is specified.
* ``dfhack.buildings.constructBuilding{...}``
Creates a building in one call, using options contained
in the argument table. Returns the building, or *nil, error*.
**NOTE:** Despite the name, unless the building is abstract,
the function creates it in an 'unconstructed' stage, with
a queued in-game job that will actually construct it. I.e.
the function replicates programmatically what can be done
through the construct building menu in the game ui, except
that it does less environment constraint checking.
The following options can be used:
- ``pos = coordinates``, or ``x = ..., y = ..., z = ...``
Mandatory. Specifies the left upper corner of the building.
- ``type = df.building_type.FOO, subtype = ..., custom = ...``
Mandatory. Specifies the type of the building. Obviously, subtype
and custom are only expected if the type requires them.
- ``fields = { ... }``
Initializes fields of the building object after creation with ``df.assign``.
- ``width = ..., height = ..., direction = ...``
Sets size and orientation of the building. If it is
fixed-size, specified dimensions are ignored.
- ``full_rectangle = true``
For buildings like stockpiles or farm plots that can normally
accomodate individual tile exclusion, forces an error if any
tiles within the specified width*height are obstructed.
- ``items = { item, item ... }``, or ``filters = { {...}, {...}... }``
Specifies explicit items or item filters to use in construction.
It is the job of the user to ensure they are correct for the building type.
- ``abstract = true``
Specifies that the building is abstract and does not require construction.
Required for stockpiles and civzones; an error otherwise.
- ``material = {...}, mechanism = {...}, ...``
If none of ``items``, ``filter``, or ``abstract`` is used,
the function uses ``getFiltersByType`` to compute the input
item filters, and passes the argument table through. If no filters
can be determined this way, ``constructBuilding`` throws an error.
Constructions module Constructions module
-------------------- --------------------

@ -1026,7 +1026,7 @@ Returns <em>false</em> in case of error.</p>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getTileBlock(coords)</tt>, or <tt class="docutils literal">getTileBlock(x,y,z)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.getTileBlock(coords)</tt>, or <tt class="docutils literal">getTileBlock(x,y,z)</tt></p>
<p>Returns a map block object for given df::coord or x,y,z in local tile coordinates.</p> <p>Returns a map block object for given df::coord or x,y,z in local tile coordinates.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getRegionBiome(region_coord2d)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.getRegionBiome(region_coord2d)</tt>, or <tt class="docutils literal">getRegionBiome(x,y)</tt></p>
<p>Returns the biome info struct for the given global map region.</p> <p>Returns the biome info struct for the given global map region.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.maps.enableBlockUpdates(block[,flow,temperature])</span></tt></p> <li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.maps.enableBlockUpdates(block[,flow,temperature])</span></tt></p>
@ -1038,6 +1038,9 @@ Returns <em>false</em> in case of error.</p>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getLocalInitFeature(region_coord2d,index)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.getLocalInitFeature(region_coord2d,index)</tt></p>
<p>Returns the local feature object with the given region coords and index.</p> <p>Returns the local feature object with the given region coords and index.</p>
</li> </li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.getTileBiomeRgn(coords)</tt>, or <tt class="docutils literal">getTileBiomeRgn(x,y,z)</tt></p>
<p>Returns <em>x, y</em> for use with <tt class="docutils literal">getRegionBiome</tt>.</p>
</li>
<li><p class="first"><tt class="docutils literal">dfhack.maps.canWalkBetween(pos1, pos2)</tt></p> <li><p class="first"><tt class="docutils literal">dfhack.maps.canWalkBetween(pos1, pos2)</tt></p>
<p>Checks if a dwarf may be able to walk between the two tiles, <p>Checks if a dwarf may be able to walk between the two tiles,
using a pathfinding cache maintained by the game. Note that using a pathfinding cache maintained by the game. Note that
@ -1160,6 +1163,69 @@ Returns <em>true</em> if the building was destroyed and deallocated immediately.
</ul> </ul>
<p>More high-level functions are implemented in lua and can be loaded by <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> <tt class="docutils literal"><span class="pre">require('dfhack.buildings')</span></tt>. See <tt class="docutils literal">hack/lua/dfhack/buildings.lua</tt>.</p>
<p>Among them are:</p>
<ul>
<li><p class="first"><tt class="docutils literal">dfhack.buildings.getFiltersByType(argtable,type,subtype,custom)</tt></p>
<p>Returns a sequence of lua structures, describing input item filters
suitable for the specified building type, or <em>nil</em> if unknown or invalid.
The returned sequence is suitable for use as the <tt class="docutils literal">job_items</tt> argument
of <tt class="docutils literal">constructWithFilters</tt>.
Uses tables defined in <tt class="docutils literal">buildings.lua</tt>.</p>
<p>Argtable members <tt class="docutils literal">material</tt> (the default name), <tt class="docutils literal">bucket</tt>, <tt class="docutils literal">barrel</tt>,
<tt class="docutils literal">chain</tt>, <tt class="docutils literal">mechanism</tt>, <tt class="docutils literal">screw</tt>, <tt class="docutils literal">pipe</tt>, <tt class="docutils literal">anvil</tt>, <tt class="docutils literal">weapon</tt> are used to
augment the basic attributes with more detailed information if the
building has input items with the matching name (see the tables for naming details).
Note that it is impossible to <em>override</em> any properties this way, only supply those that
are not mentioned otherwise; one exception is that flags2.non_economic
is automatically cleared if an explicit material is specified.</p>
</li>
<li><p class="first"><tt class="docutils literal"><span class="pre">dfhack.buildings.constructBuilding{...}</span></tt></p>
<p>Creates a building in one call, using options contained
in the argument table. Returns the building, or <em>nil, error</em>.</p>
<p><strong>NOTE:</strong> Despite the name, unless the building is abstract,
the function creates it in an 'unconstructed' stage, with
a queued in-game job that will actually construct it. I.e.
the function replicates programmatically what can be done
through the construct building menu in the game ui, except
that it does less environment constraint checking.</p>
<p>The following options can be used:</p>
<ul>
<li><p class="first"><tt class="docutils literal">pos = coordinates</tt>, or <tt class="docutils literal">x = <span class="pre">...,</span> y = <span class="pre">...,</span> z = ...</tt></p>
<p>Mandatory. Specifies the left upper corner of the building.</p>
</li>
<li><p class="first"><tt class="docutils literal">type = df.building_type.FOO, subtype = <span class="pre">...,</span> custom = ...</tt></p>
<p>Mandatory. Specifies the type of the building. Obviously, subtype
and custom are only expected if the type requires them.</p>
</li>
<li><p class="first"><tt class="docutils literal">fields = { ... }</tt></p>
<p>Initializes fields of the building object after creation with <tt class="docutils literal">df.assign</tt>.</p>
</li>
<li><p class="first"><tt class="docutils literal">width = <span class="pre">...,</span> height = <span class="pre">...,</span> direction = ...</tt></p>
<p>Sets size and orientation of the building. If it is
fixed-size, specified dimensions are ignored.</p>
</li>
<li><p class="first"><tt class="docutils literal">full_rectangle = true</tt></p>
<p>For buildings like stockpiles or farm plots that can normally
accomodate individual tile exclusion, forces an error if any
tiles within the specified width*height are obstructed.</p>
</li>
<li><p class="first"><tt class="docutils literal">items = { item, item ... }</tt>, or <tt class="docutils literal">filters = { <span class="pre">{...},</span> <span class="pre">{...}...</span> }</tt></p>
<p>Specifies explicit items or item filters to use in construction.
It is the job of the user to ensure they are correct for the building type.</p>
</li>
<li><p class="first"><tt class="docutils literal">abstract = true</tt></p>
<p>Specifies that the building is abstract and does not require construction.
Required for stockpiles and civzones; an error otherwise.</p>
</li>
<li><p class="first"><tt class="docutils literal">material = <span class="pre">{...},</span> mechanism = <span class="pre">{...},</span> ...</tt></p>
<p>If none of <tt class="docutils literal">items</tt>, <tt class="docutils literal">filter</tt>, or <tt class="docutils literal">abstract</tt> is used,
the function uses <tt class="docutils literal">getFiltersByType</tt> to compute the input
item filters, and passes the argument table through. If no filters
can be determined this way, <tt class="docutils literal">constructBuilding</tt> throws an error.</p>
</li>
</ul>
</li>
</ul>
</div> </div>
<div class="section" id="constructions-module"> <div class="section" id="constructions-module">
<h3><a class="toc-backref" href="#id21">Constructions module</a></h3> <h3><a class="toc-backref" href="#id21">Constructions module</a></h3>

@ -94,6 +94,26 @@ void Lua::Push(lua_State *state, const Units::NoblePosition &pos)
lua_setfield(state, -2, "position"); lua_setfield(state, -2, "position");
} }
void Lua::Push(lua_State *state, df::coord pos)
{
lua_createtable(state, 0, 3);
lua_pushinteger(state, pos.x);
lua_setfield(state, -2, "x");
lua_pushinteger(state, pos.y);
lua_setfield(state, -2, "y");
lua_pushinteger(state, pos.z);
lua_setfield(state, -2, "z");
}
void Lua::Push(lua_State *state, df::coord2d pos)
{
lua_createtable(state, 0, 2);
lua_pushinteger(state, pos.x);
lua_setfield(state, -2, "x");
lua_pushinteger(state, pos.y);
lua_setfield(state, -2, "y");
}
int Lua::PushPosXYZ(lua_State *state, df::coord pos) int Lua::PushPosXYZ(lua_State *state, df::coord pos)
{ {
if (!pos.isValid()) if (!pos.isValid())
@ -110,6 +130,21 @@ int Lua::PushPosXYZ(lua_State *state, df::coord pos)
} }
} }
int Lua::PushPosXY(lua_State *state, df::coord2d pos)
{
if (!pos.isValid())
{
lua_pushnil(state);
return 1;
}
else
{
lua_pushinteger(state, pos.x);
lua_pushinteger(state, pos.y);
return 2;
}
}
static df::coord2d CheckCoordXY(lua_State *state, int base, bool vararg = false) static df::coord2d CheckCoordXY(lua_State *state, int base, bool vararg = false)
{ {
df::coord2d p; df::coord2d p;
@ -754,7 +789,6 @@ static const luaL_Reg dfhack_items_funcs[] = {
static const LuaWrapper::FunctionReg dfhack_maps_module[] = { static const LuaWrapper::FunctionReg dfhack_maps_module[] = {
WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock), WRAPN(getBlock, (df::map_block* (*)(int32_t,int32_t,int32_t))Maps::getBlock),
WRAPM(Maps, getRegionBiome),
WRAPM(Maps, enableBlockUpdates), WRAPM(Maps, enableBlockUpdates),
WRAPM(Maps, getGlobalInitFeature), WRAPM(Maps, getGlobalInitFeature),
WRAPM(Maps, getLocalInitFeature), WRAPM(Maps, getLocalInitFeature),
@ -769,8 +803,24 @@ static int maps_getTileBlock(lua_State *L)
return 1; return 1;
} }
static int maps_getRegionBiome(lua_State *L)
{
auto pos = CheckCoordXY(L, 1, true);
Lua::PushDFObject(L, Maps::getRegionBiome(pos));
return 1;
}
static int maps_getTileBiomeRgn(lua_State *L)
{
auto pos = CheckCoordXYZ(L, 1, true);
Lua::PushPosXY(L, Maps::getTileBiomeRgn(pos));
return 1;
}
static const luaL_Reg dfhack_maps_funcs[] = { static const luaL_Reg dfhack_maps_funcs[] = {
{ "getTileBlock", maps_getTileBlock }, { "getTileBlock", maps_getTileBlock },
{ "getRegionBiome", maps_getRegionBiome },
{ "getTileBiomeRgn", maps_getTileBiomeRgn },
{ NULL, NULL } { NULL, NULL }
}; };

@ -264,11 +264,14 @@ namespace DFHack {namespace Lua {
inline void Push(lua_State *state, bool value) { inline void Push(lua_State *state, bool value) {
lua_pushboolean(state, value); lua_pushboolean(state, value);
} }
inline void Push(lua_State *state, const char *str) {
lua_pushstring(state, str);
}
inline void Push(lua_State *state, const std::string &str) { inline void Push(lua_State *state, const std::string &str) {
lua_pushlstring(state, str.data(), str.size()); lua_pushlstring(state, str.data(), str.size());
} }
inline void Push(lua_State *state, df::coord &obj) { PushDFObject(state, &obj); } DFHACK_EXPORT void Push(lua_State *state, df::coord obj);
inline void Push(lua_State *state, df::coord2d &obj) { PushDFObject(state, &obj); } DFHACK_EXPORT void Push(lua_State *state, df::coord2d obj);
void Push(lua_State *state, const Units::NoblePosition &pos); void Push(lua_State *state, const Units::NoblePosition &pos);
template<class T> inline void Push(lua_State *state, T *ptr) { template<class T> inline void Push(lua_State *state, T *ptr) {
PushDFObject(state, ptr); PushDFObject(state, ptr);
@ -293,6 +296,7 @@ namespace DFHack {namespace Lua {
} }
DFHACK_EXPORT int PushPosXYZ(lua_State *state, df::coord pos); DFHACK_EXPORT int PushPosXYZ(lua_State *state, df::coord pos);
DFHACK_EXPORT int PushPosXY(lua_State *state, df::coord2d pos);
DFHACK_EXPORT bool IsCoreContext(lua_State *state); DFHACK_EXPORT bool IsCoreContext(lua_State *state);

@ -255,8 +255,20 @@ inline df::tile_occupancy *getTileOccupancy(df::coord pos) {
return getTileOccupancy(pos.x, pos.y, pos.z); return getTileOccupancy(pos.x, pos.y, pos.z);
} }
/**
* Returns biome info about the specified world region.
*/
DFHACK_EXPORT df::world_data::T_region_map *getRegionBiome(df::coord2d rgn_pos); DFHACK_EXPORT df::world_data::T_region_map *getRegionBiome(df::coord2d rgn_pos);
/**
* Returns biome world region coordinates for the given tile within given block.
*/
DFHACK_EXPORT df::coord2d getBlockTileBiomeRgn(df::map_block *block, df::coord2d pos);
inline df::coord2d getTileBiomeRgn(df::coord pos) {
return getBlockTileBiomeRgn(getTileBlock(pos), pos);
}
// Enables per-frame updates for liquid flow and/or temperature. // Enables per-frame updates for liquid flow and/or temperature.
DFHACK_EXPORT void enableBlockUpdates(df::map_block *blk, bool flow = false, bool temperature = false); DFHACK_EXPORT void enableBlockUpdates(df::map_block *blk, bool flow = false, bool temperature = false);

@ -111,9 +111,11 @@ function copyall(table)
end end
function pos2xyz(pos) function pos2xyz(pos)
local x = pos.x if pos then
if x and x ~= -30000 then local x = pos.x
return x, pos.y, pos.z if x and x ~= -30000 then
return x, pos.y, pos.z
end
end end
end end

@ -4,7 +4,32 @@ local buildings = dfhack.buildings
local utils = require 'utils' local utils = require 'utils'
--[[ Building input material tables. ]] -- Uninteresting values for filter attributes when reading them from DF memory.
-- Differs from the actual defaults of the job_item constructor in allow_artifact.
buildings.input_filter_defaults = {
item_type = -1,
item_subtype = -1,
mat_type = -1,
mat_index = -1,
flags1 = {},
-- Instead of noting those that allow artifacts, mark those that forbid them.
-- Leaves actually enabling artifacts to the discretion of the API user,
-- which is the right thing because unlike the game UI these filters are
-- used in a way that does not give the user a chance to choose manually.
flags2 = { allow_artifact = true },
flags3 = {},
flags4 = 0,
flags5 = 0,
reaction_class = '',
has_material_reaction_product = '',
metal_ore = -1,
min_dimension = -1,
has_tool_use = -1,
quantity = 1
}
--[[ Building input material table. ]]
local building_inputs = { local building_inputs = {
[df.building_type.Chair] = { { item_type=df.item_type.CHAIR, vector_id=df.job_item_vector_id.CHAIR } }, [df.building_type.Chair] = { { item_type=df.item_type.CHAIR, vector_id=df.job_item_vector_id.CHAIR } },
@ -12,7 +37,6 @@ local building_inputs = {
[df.building_type.Table] = { { item_type=df.item_type.TABLE, vector_id=df.job_item_vector_id.TABLE } }, [df.building_type.Table] = { { item_type=df.item_type.TABLE, vector_id=df.job_item_vector_id.TABLE } },
[df.building_type.Coffin] = { { item_type=df.item_type.COFFIN, vector_id=df.job_item_vector_id.COFFIN } }, [df.building_type.Coffin] = { { item_type=df.item_type.COFFIN, vector_id=df.job_item_vector_id.COFFIN } },
[df.building_type.FarmPlot] = { }, [df.building_type.FarmPlot] = { },
[df.building_type.Furnace] = { { flags2={ building_material=true, fire_safe=true, non_economic=true } } },
[df.building_type.TradeDepot] = { { flags2={ building_material=true, non_economic=true }, quantity=3 } }, [df.building_type.TradeDepot] = { { flags2={ building_material=true, non_economic=true }, quantity=3 } },
[df.building_type.Door] = { { item_type=df.item_type.DOOR, vector_id=df.job_item_vector_id.DOOR } }, [df.building_type.Door] = { { item_type=df.item_type.DOOR, vector_id=df.job_item_vector_id.DOOR } },
[df.building_type.Floodgate] = { [df.building_type.Floodgate] = {
@ -40,7 +64,6 @@ local building_inputs = {
vector_id=df.job_item_vector_id.ARMORSTAND vector_id=df.job_item_vector_id.ARMORSTAND
} }
}, },
[df.building_type.Workshop] = { { flags2={ building_material=true, non_economic=true } } },
[df.building_type.Cabinet] = { [df.building_type.Cabinet] = {
{ item_type=df.item_type.CABINET, vector_id=df.job_item_vector_id.CABINET } { item_type=df.item_type.CABINET, vector_id=df.job_item_vector_id.CABINET }
}, },
@ -89,7 +112,7 @@ local building_inputs = {
[df.building_type.ArcheryTarget] = { { flags2={ building_material=true, non_economic=true } } }, [df.building_type.ArcheryTarget] = { { flags2={ building_material=true, non_economic=true } } },
[df.building_type.Chain] = { { item_type=df.item_type.CHAIN, vector_id=df.job_item_vector_id.CHAIN } }, [df.building_type.Chain] = { { item_type=df.item_type.CHAIN, vector_id=df.job_item_vector_id.CHAIN } },
[df.building_type.Cage] = { { item_type=df.item_type.CAGE, vector_id=df.job_item_vector_id.CAGE } }, [df.building_type.Cage] = { { item_type=df.item_type.CAGE, vector_id=df.job_item_vector_id.CAGE } },
[df.building_type.Weapon] = { { vector_id=df.job_item_vector_id.ANY_SPIKE } }, [df.building_type.Weapon] = { { name='weapon', vector_id=df.job_item_vector_id.ANY_SPIKE } },
[df.building_type.ScrewPump] = { [df.building_type.ScrewPump] = {
{ {
item_type=df.item_type.BLOCKS, item_type=df.item_type.BLOCKS,
@ -158,6 +181,8 @@ local building_inputs = {
[df.building_type.Hive] = { { has_tool_use=df.tool_uses.HIVE, item_type=df.item_type.TOOL } } [df.building_type.Hive] = { { has_tool_use=df.tool_uses.HIVE, item_type=df.item_type.TOOL } }
} }
--[[ Furnace building input material table. ]]
local furnace_inputs = { local furnace_inputs = {
[df.furnace_type.WoodFurnace] = { { flags2={ building_material=true, fire_safe=true, non_economic=true } } }, [df.furnace_type.WoodFurnace] = { { flags2={ building_material=true, fire_safe=true, non_economic=true } } },
[df.furnace_type.Smelter] = { { flags2={ building_material=true, fire_safe=true, non_economic=true } } }, [df.furnace_type.Smelter] = { { flags2={ building_material=true, fire_safe=true, non_economic=true } } },
@ -168,6 +193,8 @@ local furnace_inputs = {
[df.furnace_type.MagmaKiln] = { { flags2={ building_material=true, magma_safe=true, non_economic=true } } } [df.furnace_type.MagmaKiln] = { { flags2={ building_material=true, magma_safe=true, non_economic=true } } }
} }
--[[ Workshop building input material table. ]]
local workshop_inputs = { local workshop_inputs = {
[df.workshop_type.Carpenters] = { { flags2={ building_material=true, non_economic=true } } }, [df.workshop_type.Carpenters] = { { flags2={ building_material=true, non_economic=true } } },
[df.workshop_type.Farmers] = { { flags2={ building_material=true, non_economic=true } } }, [df.workshop_type.Farmers] = { { flags2={ building_material=true, non_economic=true } } },
@ -250,6 +277,8 @@ local workshop_inputs = {
} }
} }
--[[ Trap building input material table. ]]
local trap_inputs = { local trap_inputs = {
[df.trap_type.StoneFallTrap] = { [df.trap_type.StoneFallTrap] = {
{ {
@ -264,7 +293,10 @@ local trap_inputs = {
item_type=df.item_type.TRAPPARTS, item_type=df.item_type.TRAPPARTS,
vector_id=df.job_item_vector_id.TRAPPARTS vector_id=df.job_item_vector_id.TRAPPARTS
}, },
{ vector_id=df.job_item_vector_id.ANY_WEAPON } {
name='weapon',
vector_id=df.job_item_vector_id.ANY_WEAPON
}
}, },
[df.trap_type.Lever] = { [df.trap_type.Lever] = {
{ {
@ -289,11 +321,28 @@ local trap_inputs = {
} }
} }
--[[ Functions for lookup in tables. ]]
local function get_custom_inputs(custom)
local defn = df.building_def.find(custom)
if defn ~= nil then
return utils.clone_with_default(defn.build_items, buildings.input_filter_defaults)
end
end
local function get_inputs_by_type(type,subtype,custom) local function get_inputs_by_type(type,subtype,custom)
if type == df.building_type.Workshop then if type == df.building_type.Workshop then
return workshop_inputs[subtype] if subtype == df.workshop_type.Custom then
return get_custom_inputs(custom)
else
return workshop_inputs[subtype]
end
elseif type == df.building_type.Furnace then elseif type == df.building_type.Furnace then
return furnace_inputs[subtype] if subtype == df.furnace_type.Custom then
return get_custom_inputs(custom)
else
return furnace_inputs[subtype]
end
elseif type == df.building_type.Trap then elseif type == df.building_type.Trap then
return trap_inputs[subtype] return trap_inputs[subtype]
else else
@ -357,7 +406,7 @@ end
-- Materials: -- Materials:
items = { item, item ... }, items = { item, item ... },
-- OR -- OR
filter = { { ... }, { ... }... } filters = { { ... }, { ... }... }
-- OR -- OR
abstract = true abstract = true
-- OR -- OR

@ -221,6 +221,68 @@ function clone(obj,deep)
end end
end end
local function get_default(default,key,base)
if type(default) == 'table' then
local dv = default[key]
if dv == nil then
dv = default._default
end
if dv == nil then
dv = base
end
return dv
else
return default
end
end
-- Copy the object as lua data structures, skipping values matching defaults.
function clone_with_default(obj,default,force)
local rv = nil
local function setrv(k,v)
if v ~= nil then
if rv == nil then
rv = {}
end
rv[k] = v
end
end
if default == nil then
return nil
elseif type(obj) == 'table' then
for k,v in pairs(obj) do
setrv(k, clone_with_default(v, get_default(default,k)))
end
elseif df.isvalid(obj) == 'ref' then
local kind = obj._kind
if kind == 'primitive' then
return clone_with_default(obj.value,default,force)
elseif kind == 'bitfield' then
for k,v in pairs(obj) do
setrv(k, clone_with_default(v, get_default(default,k,false)))
end
elseif kind == 'container' then
for k,v in ipairs(obj) do
setrv(k+1, clone_with_default(v, default, true))
end
else -- struct
for k,v in pairs(obj) do
setrv(k, clone_with_default(v, get_default(default,k)))
end
end
elseif obj == default and not force then
return nil
elseif obj == nil then
return NULL
else
return obj
end
if force and rv == nil then
rv = {}
end
return rv
end
-- Sort a vector or lua table -- Sort a vector or lua table
function sort_vector(vector,field,cmp) function sort_vector(vector,field,cmp)
local fcmp = compare_field(field,cmp) local fcmp = compare_field(field,cmp)

@ -369,6 +369,39 @@ bool Maps::RemoveBlockEvent(uint32_t x, uint32_t y, uint32_t z, df::block_square
return false; return false;
} }
static df::coord2d biome_offsets[9] = {
df::coord2d(-1,-1), df::coord2d(0,-1), df::coord2d(1,-1),
df::coord2d(-1,0), df::coord2d(0,0), df::coord2d(1,0),
df::coord2d(-1,1), df::coord2d(0,1), df::coord2d(1,1)
};
inline df::coord2d getBiomeRgnPos(df::coord2d base, int idx)
{
auto r = base + biome_offsets[idx];
int world_width = world->world_data->world_width;
int world_height = world->world_data->world_height;
return df::coord2d(clip_range(r.x,0,world_width-1),clip_range(r.y,0,world_height-1));
}
df::coord2d Maps::getBlockTileBiomeRgn(df::map_block *block, df::coord2d pos)
{
if (!block || !world->world_data)
return df::coord2d();
auto des = MapExtras::index_tile<df::tile_designation>(block->designation,pos);
unsigned idx = des.bits.biome;
if (idx < 9)
{
idx = block->region_offset[idx];
if (idx < 9)
return getBiomeRgnPos(block->region_pos, idx);
}
return df::coord2d();
}
/* /*
* Layer geology * Layer geology
*/ */
@ -386,20 +419,14 @@ bool Maps::ReadGeology(vector<vector<int16_t> > *layer_mats, vector<df::coord2d>
(*geoidx)[i] = df::coord2d(-30000,-30000); (*geoidx)[i] = df::coord2d(-30000,-30000);
} }
int world_width = world->world_data->world_width; // regionX is in embark squares
int world_height = world->world_data->world_height; // regionX/16 is in 16x16 embark square regions
df::coord2d map_region(world->map.region_x / 16, world->map.region_y / 16);
// iterate over 8 surrounding regions + local region // iterate over 8 surrounding regions + local region
for (int i = eNorthWest; i < eBiomeCount; i++) for (int i = eNorthWest; i < eBiomeCount; i++)
{ {
// check against worldmap boundaries, fix if needed df::coord2d rgn_pos = getBiomeRgnPos(map_region, i);
// regionX is in embark squares
// regionX/16 is in 16x16 embark square regions
// i provides -1 .. +1 offset from the current region
int bioRX = world->map.region_x / 16 + ((i % 3) - 1);
int bioRY = world->map.region_y / 16 + ((i / 3) - 1);
df::coord2d rgn_pos(clip_range(bioRX,0,world_width-1),clip_range(bioRY,0,world_height-1));
(*geoidx)[i] = rgn_pos; (*geoidx)[i] = rgn_pos;

@ -1,43 +1,29 @@
-- List input items for the building currently being built. -- List input items for the building currently being built.
--
-- This is where the filters in lua/dfhack/buildings.lua come from.
local dumper = require 'dumper' local dumper = require 'dumper'
local utils = require 'utils'
local buildings = require 'dfhack.buildings'
local function copy_flags(tgt,src,name) local function name_enum(tgt,name,ename,enum)
local val = src[name] if tgt[name] ~= nil then
if val.whole == 0 then tgt[name] = ename..'.'..enum[tgt[name]]
return
end
local out = {}
tgt[name] = out
for k,v in pairs(val) do
if v then
out[k] = v
end
end
end
local function copy_value(tgt,src,name,defval)
if src[name] ~= defval then
tgt[name] = src[name]
end
end
local function copy_enum(tgt,src,name,defval,ename,enum)
if src[name] ~= defval then
tgt[name] = ename..'.'..enum[src[name]]
end end
end end
local lookup = {} local lookup = {}
local items = df.global.world.items
for i=df.job_item_vector_id._first_item,df.job_item_vector_id._last_item do for i=df.job_item_vector_id._first_item,df.job_item_vector_id._last_item do
local id = df.job_item_vector_id.attrs[i].other local id = df.job_item_vector_id.attrs[i].other
local ptr local ptr
if id == df.items_other_id.ANY then if id == df.items_other_id.ANY then
ptr = df.global.world.items.all ptr = items.all
elseif id == df.items_other_id.BAD then elseif id == df.items_other_id.BAD then
ptr = df.global.world.items.bad ptr = items.bad
else else
ptr = df.global.world.items.other[id] ptr = items.other[id]
end end
if ptr then if ptr then
local _,addr = df.sizeof(ptr) local _,addr = df.sizeof(ptr)
@ -46,23 +32,12 @@ for i=df.job_item_vector_id._first_item,df.job_item_vector_id._last_item do
end end
local function clone_filter(src,quantity) local function clone_filter(src,quantity)
local tgt = {} local tgt = utils.clone_with_default(src, buildings.input_filter_defaults, true)
src.flags2.allow_artifact = false
if quantity ~= 1 then if quantity ~= 1 then
tgt.quantity = quantity tgt.quantity = quantity
end end
copy_enum(tgt, src, 'item_type', -1, 'df.item_type', df.item_type) name_enum(tgt, 'item_type', 'df.item_type', df.item_type)
copy_value(tgt, src, 'item_subtype', -1) name_enum(tgt, 'has_tool_use', 'df.tool_uses', df.tool_uses)
copy_value(tgt, src, 'mat_type', -1)
copy_value(tgt, src, 'mat_index', -1)
copy_flags(tgt, src, 'flags1')
copy_flags(tgt, src, 'flags2')
copy_flags(tgt, src, 'flags3')
copy_value(tgt, src, 'reaction_class', '')
copy_value(tgt, src, 'has_material_reaction_product', '')
copy_value(tgt, src, 'metal_ore', -1)
copy_value(tgt, src, 'min_dimension', -1)
copy_enum(tgt, src, 'has_tool_use', -1, 'df.tool_uses', df.tool_uses)
local ptr = src.item_vector local ptr = src.item_vector
if ptr and ptr ~= df.global.world.items.other[0] then if ptr and ptr ~= df.global.world.items.other[0] then
local _,addr = df.sizeof(ptr) local _,addr = df.sizeof(ptr)
@ -78,8 +53,9 @@ local function dump(name)
end end
local fmt = dumper.DataDumper(out,name,false,1,4) local fmt = dumper.DataDumper(out,name,false,1,4)
local out = string.gsub(fmt, '"', '') fmt = string.gsub(fmt, '"(df%.[^"]+)"','%1')
print(out) fmt = string.gsub(fmt, '%s+$', '')
print(fmt)
end end
local itype = df.global.ui_build_selector.building_type local itype = df.global.ui_build_selector.building_type