diff options
| author | Alexander Gavrilov | 2012-05-06 19:09:11 +0400 |
|---|---|---|
| committer | Alexander Gavrilov | 2012-05-06 19:09:11 +0400 |
| commit | 9ad8d767b4fcf0946444469d2c4072d46997b7e6 (patch) | |
| tree | f49a082895fe73d400e64359e859806c173d00ef | |
| parent | b70130cf3684d8adbf36023b27aec0f10b213cc7 (diff) | |
| download | dfhack-9ad8d767b4fcf0946444469d2c4072d46997b7e6.tar.gz dfhack-9ad8d767b4fcf0946444469d2c4072d46997b7e6.tar.bz2 dfhack-9ad8d767b4fcf0946444469d2c4072d46997b7e6.tar.xz | |
Add code for adding abstract buildings and removing constructions.
| -rw-r--r-- | LUA_API.rst | 17 | ||||
| -rw-r--r-- | Lua API.html | 14 | ||||
| -rw-r--r-- | library/LuaApi.cpp | 16 | ||||
| -rw-r--r-- | library/include/modules/Buildings.h | 11 | ||||
| -rw-r--r-- | library/include/modules/Constructions.h | 3 | ||||
| -rw-r--r-- | library/lua/dfhack/buildings.lua | 10 | ||||
| -rw-r--r-- | library/modules/Buildings.cpp | 121 | ||||
| -rw-r--r-- | library/modules/Constructions.cpp | 40 |
8 files changed, 229 insertions, 3 deletions
diff --git a/LUA_API.rst b/LUA_API.rst index 681caef5..e20b946d 100644 --- a/LUA_API.rst +++ b/LUA_API.rst @@ -926,6 +926,12 @@ Low-level building creation functions; final values used by the building; true_area is less than rect_area if any tiles were removed from designation. +* ``dfhack.buildings.constructAbstract(building)`` + + Links a fully configured object created by ``allocInstance`` into the + world. The object must be an abstract building, i.e. a stockpile or civzone. + Returns *true*, or *false* if impossible. + * ``dfhack.buildings.constructWithItems(building, items)`` Links a fully configured object created by ``allocInstance`` into the @@ -941,6 +947,11 @@ Low-level building creation functions; Use a negative ``quantity`` field value to auto-compute the amount from the size of the building. +* ``dfhack.buildings.deconstruct(building)`` + + Destroys the building, or queues a deconstruction job. + Returns *true* if the building was destroyed and deallocated immediately. + More high-level functions are implemented in lua and can be loaded by ``require('dfhack.buildings')``. See ``hack/lua/dfhack/buildings.lua``. @@ -954,6 +965,12 @@ Constructions module Returns *true*, or *false* if obstructed. Note that designated constructions are technically buildings. +* ``dfhack.constructions.designateRemove(pos)``, or ``designateRemove(x,y,z)`` + + If there is a construction or a planned construction at the specified + coordinates, designates it for removal, or instantly cancels the planned one. + Returns *true, was_only_planned* if removed; or *false* if none found. + Core interpreter context ======================== diff --git a/Lua API.html b/Lua API.html index 094b522c..7aa8e651 100644 --- a/Lua API.html +++ b/Lua API.html @@ -1126,6 +1126,11 @@ 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> </li> +<li><p class="first"><tt class="docutils literal">dfhack.buildings.constructAbstract(building)</tt></p> +<p>Links a fully configured object created by <tt class="docutils literal">allocInstance</tt> into the +world. The object must be an abstract building, i.e. a stockpile or civzone. +Returns <em>true</em>, or <em>false</em> if impossible.</p> +</li> <li><p class="first"><tt class="docutils literal">dfhack.buildings.constructWithItems(building, items)</tt></p> <p>Links a fully configured object created by <tt class="docutils literal">allocInstance</tt> into the world for construction, using a list of specific items as material. @@ -1139,6 +1144,10 @@ and possibly destroyed in any case. Use a negative <tt class="docutils literal">quantity</tt> field value to auto-compute the amount from the size of the building.</p> </li> +<li><p class="first"><tt class="docutils literal">dfhack.buildings.deconstruct(building)</tt></p> +<p>Destroys the building, or queues a deconstruction job. +Returns <em>true</em> if the building was destroyed and deallocated immediately.</p> +</li> </ul> <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> @@ -1152,6 +1161,11 @@ a planned but not completed construction there, changes its type. Returns <em>true</em>, or <em>false</em> if obstructed. Note that designated constructions are technically buildings.</p> </li> +<li><p class="first"><tt class="docutils literal">dfhack.constructions.designateRemove(pos)</tt>, or <tt class="docutils literal">designateRemove(x,y,z)</tt></p> +<p>If there is a construction or a planned construction at the specified +coordinates, designates it for removal, or instantly cancels the planned one. +Returns <em>true, was_only_planned</em> if removed; or <em>false</em> if none found.</p> +</li> </ul> </div> </div> diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index bf2ec936..d554754e 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -821,8 +821,10 @@ static const LuaWrapper::FunctionReg dfhack_buildings_module[] = { WRAPM(Buildings, countExtentTiles), WRAPN(containsTile, buildings_containsTile), WRAPM(Buildings, hasSupport), + WRAPM(Buildings, constructAbstract), WRAPM(Buildings, constructWithItems), WRAPM(Buildings, constructWithFilters), + WRAPM(Buildings, deconstruct), { NULL, NULL } }; @@ -900,6 +902,20 @@ static const LuaWrapper::FunctionReg dfhack_constructions_module[] = { { NULL, NULL } }; +static int constructions_designateRemove(lua_State *L) +{ + auto pos = CheckCoordXYZ(L, 1, true); + bool imm = false; + lua_pushboolean(L, Constructions::designateRemove(pos, &imm)); + lua_pushboolean(L, imm); + return 2; +} + +static const luaL_Reg dfhack_constructions_funcs[] = { + { "designateRemove", constructions_designateRemove }, + { NULL, NULL } +}; + /************************ * Main Open function * diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h index 9bb3ba00..6e0a2205 100644 --- a/library/include/modules/Buildings.h +++ b/library/include/modules/Buildings.h @@ -150,6 +150,11 @@ DFHACK_EXPORT bool setSize(df::building *bld, df::coord2d size, int direction = DFHACK_EXPORT std::pair<df::coord,df::coord2d> getSize(df::building *bld); /** + * Constructs an abstract building, i.e. stockpile or civzone. + */ +DFHACK_EXPORT bool constructAbstract(df::building *bld); + +/** * Initiates construction of the building, using specified items as inputs. * Returns true if success. */ @@ -162,5 +167,11 @@ DFHACK_EXPORT bool constructWithItems(df::building *bld, std::vector<df::item*> */ DFHACK_EXPORT bool constructWithFilters(df::building *bld, std::vector<df::job_item*> items); +/** + * Deconstructs or queues deconstruction of a building. + * Returns true if the building has been destroyed instantly. + */ +DFHACK_EXPORT bool deconstruct(df::building *bld); + } } diff --git a/library/include/modules/Constructions.h b/library/include/modules/Constructions.h index 17da1271..f8a3e5c6 100644 --- a/library/include/modules/Constructions.h +++ b/library/include/modules/Constructions.h @@ -62,6 +62,9 @@ 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); + +DFHACK_EXPORT bool designateRemove(df::coord pos, bool *immediate = NULL); + } } #endif diff --git a/library/lua/dfhack/buildings.lua b/library/lua/dfhack/buildings.lua index 57427e9f..9650dc4c 100644 --- a/library/lua/dfhack/buildings.lua +++ b/library/lua/dfhack/buildings.lua @@ -28,6 +28,8 @@ local buildings = dfhack.buildings items = { item, item ... }, -- OR filter = { { ... }, { ... }... } + -- OR + abstract = true } Returns: the created building, or 'nil, error' @@ -41,8 +43,8 @@ function buildings.constructBuilding(info) if not (info.pos or info.x) then error('position is required') end - if not (info.items or info.filters) then - error('either items or filters are required') + if not (info.abstract or info.items or info.filters) then + error('one of items, filters or abstract are required') elseif info.filters then for _,v in ipairs(info.filters) do v.new = true @@ -77,7 +79,9 @@ function buildings.constructBuilding(info) if info.full_rectangle and area ~= r_area then return nil, "not all tiles can be used" end - if info.items then + if info.abstract then + ok = buildings.constructAbstract(instance) + elseif info.items then ok = buildings.constructWithItems(instance, info.items) else ok = buildings.constructWithFilters(instance, info.filters) diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index 2c516267..557eb188 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -46,6 +46,7 @@ using namespace DFHack; #include "DataDefs.h" #include "df/world.h" #include "df/ui.h" +#include "df/ui_look_list.h" #include "df/d_init.h" #include "df/item.h" #include "df/job.h" @@ -59,6 +60,7 @@ using namespace DFHack; #include "df/building_bridgest.h" #include "df/building_coffinst.h" #include "df/building_civzonest.h" +#include "df/building_stockpilest.h" #include "df/building_furnacest.h" #include "df/building_workshopst.h" #include "df/building_screw_pumpst.h" @@ -683,6 +685,18 @@ static void linkRooms(df::building *bld) df::global::ui->equipment.update.bits.buildings = true; } +static void unlinkRooms(df::building *bld) +{ + for (size_t i = 0; i < bld->parents.size(); i++) + { + auto parent = bld->parents[i]; + int idx = linear_index(parent->children, bld); + vector_erase_at(parent->children, idx); + } + + bld->parents.clear(); +} + static void linkBuilding(df::building *bld) { bld->id = (*building_next_id)++; @@ -715,6 +729,52 @@ static void createDesign(df::building *bld, bool rough) } } +static int getMaxStockpileId() +{ + auto &vec = world->buildings.other[buildings_other_id::STOCKPILE]; + int max_id = 0; + + for (size_t i = 0; i < vec.size(); i++) + { + auto bld = strict_virtual_cast<df::building_stockpilest>(vec[i]); + if (bld) + max_id = std::max(max_id, bld->stockpile_number); + } + + return max_id; +} + +bool Buildings::constructAbstract(df::building *bld) +{ + CHECK_NULL_POINTER(bld); + CHECK_INVALID_ARGUMENT(bld->id == -1); + CHECK_INVALID_ARGUMENT(!bld->isActual()); + + if (!checkBuildingTiles(bld, false)) + return false; + + switch (bld->getType()) + { + case building_type::Stockpile: + if (auto stock = strict_virtual_cast<df::building_stockpilest>(bld)) + stock->stockpile_number = getMaxStockpileId() + 1; + break; + + default: + break; + } + + linkBuilding(bld); + + if (!bld->flags.bits.exists) + { + bld->flags.bits.exists = true; + bld->initFarmSeasons(); + } + + return true; +} + static bool linkForConstruct(df::job* &job, df::building *bld) { if (!checkBuildingTiles(bld, false)) @@ -836,3 +896,64 @@ bool Buildings::constructWithFilters(df::building *bld, std::vector<df::job_item return true; } +bool Buildings::deconstruct(df::building *bld) +{ + using df::global::ui; + using df::global::world; + using df::global::process_jobs; + using df::global::process_dig; + using df::global::ui_look_list; + + CHECK_NULL_POINTER(bld); + + if (bld->isActual() && bld->getBuildStage() > 0) + { + bld->queueDestroy(); + return false; + } + + /* Immediate destruction code path. + Should only happen for abstract and unconstructed buildings.*/ + + if (bld->isSettingOccupancy()) + { + markBuildingTiles(bld, true); + bld->cleanupMap(); + } + + bld->removeUses(false, false); + // Assume: no parties. + unlinkRooms(bld); + // Assume: not unit destroy target + vector_erase_at(ui->unk8.unk10, linear_index(ui->unk8.unk10, bld)); + // Assume: not used in punishment + // Assume: not used in non-own jobs + // Assume: does not affect pathfinding + bld->deconstructItems(false, false); + // Don't clear arrows. + + bld->uncategorize(); + delete bld; + + if (world->selected_building == bld) + { + world->selected_building = NULL; + world->update_selected_building = true; + } + + for (int i = ui_look_list->items.size()-1; i >= 0; i--) + { + auto item = ui_look_list->items[i]; + if (item->type == df::ui_look_list::T_items::Building && + item->building == bld) + { + vector_erase_at(ui_look_list->items, i); + delete item; + } + } + + if (process_dig) *process_dig = true; + if (process_jobs) *process_jobs = true; + + return true; +} diff --git a/library/modules/Constructions.cpp b/library/modules/Constructions.cpp index a3804839..2d61c447 100644 --- a/library/modules/Constructions.cpp +++ b/library/modules/Constructions.cpp @@ -129,3 +129,43 @@ bool Constructions::designateNew(df::coord pos, df::construction_type type, return true; } +bool Constructions::designateRemove(df::coord pos, bool *immediate) +{ + using df::global::process_dig; + + if (immediate) + *immediate = false; + + if (auto current = Buildings::findAtTile(pos)) + { + auto cons = strict_virtual_cast<df::building_constructionst>(current); + if (!cons) + return false; + + if (Buildings::deconstruct(cons)) + { + if (immediate) + *immediate = true; + } + + return true; + } + + auto block = Maps::getTileBlock(pos); + if (!block) + return false; + + auto ttype = block->tiletype[pos.x&15][pos.y&15]; + + if (tileMaterial(ttype) == tiletype_material::CONSTRUCTION) + { + auto &dsgn = block->designation[pos.x&15][pos.y&15]; + dsgn.bits.dig = tile_dig_designation::Default; + block->flags.bits.designated = true; + if (process_dig) + *process_dig = true; + return true; + } + + return false; +} |
