diff --git a/docs/Lua API.rst b/docs/Lua API.rst index 7eacd7b96..2f35fabf6 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -1571,6 +1571,13 @@ Low-level building creation functions: Returns *true* if the building is marked for removal (with :kbd:`x`), *false* otherwise. +* ``dfhack.buildings.getRoomDescription(building[, unit])`` + + If the building is a room, returns a description including quality modifiers, e.g. "Royal Bedroom". + Otherwise, returns an empty string. + + The unit argument is passed through to DF and may modify the room's value depending on the unit given. + High-level ~~~~~~~~~~ More high-level functions are implemented in lua and can be loaded by diff --git a/docs/changelog.txt b/docs/changelog.txt index 0fefa4b8c..5905fbbd8 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -37,8 +37,12 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ================================================================================ # Future +## Misc Improvements +- `gui/room-list`: added support for ``Gui::getSelectedBuilding()`` + ## API - New functions (all available to Lua as well): + - ``Buildings::getRoomDescription()`` - ``Items::checkMandates()`` - ``Items::canTrade()`` - ``Items::canTradeWithContents()`` diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index af71e729b..c71a0de9d 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2001,11 +2001,12 @@ static const LuaWrapper::FunctionReg dfhack_buildings_module[] = { WRAPM(Buildings, constructWithItems), WRAPM(Buildings, constructWithFilters), WRAPM(Buildings, deconstruct), + WRAPM(Buildings, markedForRemoval), + WRAPM(Buildings, getRoomDescription), WRAPM(Buildings, isActivityZone), WRAPM(Buildings, isPenPasture), WRAPM(Buildings, isPitPond), WRAPM(Buildings, isActive), - WRAPM(Buildings, markedForRemoval), { NULL, NULL } }; diff --git a/library/include/modules/Buildings.h b/library/include/modules/Buildings.h index 4519b8164..4032b96af 100644 --- a/library/include/modules/Buildings.h +++ b/library/include/modules/Buildings.h @@ -198,6 +198,15 @@ DFHACK_EXPORT bool markedForRemoval(df::building *bld); void updateBuildings(color_ostream& out, void* ptr); void clearBuildings(color_ostream& out); +/** + * If the building is a room, returns a description including quality modifiers, e.g. "Royal Bedroom". + * Otherwise, returns an empty string. + * + * The unit argument is passed through to DF and may modify the room's value depending on the unit given. + */ + +DFHACK_EXPORT std::string getRoomDescription(df::building *building, df::unit *unit = nullptr); + /** * Iterates over the items stored on a stockpile. * (For stockpiles with containers, yields the containers, not their contents.) diff --git a/library/modules/Buildings.cpp b/library/modules/Buildings.cpp index e3d8e1d69..732956a3e 100644 --- a/library/modules/Buildings.cpp +++ b/library/modules/Buildings.cpp @@ -72,6 +72,7 @@ using namespace DFHack; #include "df/building_workshopst.h" #include "df/buildings_other_id.h" #include "df/d_init.h" +#include "df/dfhack_room_quality_level.h" #include "df/general_ref_building_holderst.h" #include "df/general_ref_contains_unitst.h" #include "df/item.h" @@ -1246,6 +1247,70 @@ void Buildings::updateBuildings(color_ostream& out, void* ptr) } } +static std::map> room_quality_names = { + {df::building_type::Bed, { + "Meager Quarters", + "Modest Quarters", + "Quarters", + "Decent Quarters", + "Fine Quarters", + "Great Bedroom", + "Grand Bedroom", + "Royal Bedroom"}}, + {df::building_type::Table, { + "Meager Dining Room", + "Modest Dining Room", + "Dining Room", + "Decent Dining Room", + "Fine Dining Room", + "Great Dining Room", + "Grand Dining Room", + "Royal Dining Room"}}, + {df::building_type::Chair, { + "Meager Office", + "Modest Office", + "Office", + "Decent Office", + "Splendid Office", + "Throne Room", + "Opulent Throne Room", + "Royal Throne Room"}}, + {df::building_type::Coffin, { + "Grave", + "Servant's Burial Chamber", + "Burial Chamber", + "Tomb", + "Fine Tomb", + "Mausoleum", + "Grand Mausoleum", + "Royal Mausoleum"}} +}; + +std::string Buildings::getRoomDescription(df::building *building, df::unit *unit) +{ + CHECK_NULL_POINTER(building); + // unit can be null + + if (!building->is_room) + return ""; + + auto btype = building->getType(); + if (room_quality_names.find(btype) == room_quality_names.end()) + return ""; + + int32_t value = building->getRoomValue(unit); + auto level = ENUM_FIRST_ITEM(dfhack_room_quality_level); + for (auto i_level = level; is_valid_enum_item(i_level); i_level = next_enum_item(i_level, false)) + { + if (value >= ENUM_ATTR(dfhack_room_quality_level, min_value, i_level)) + { + level = i_level; + } + } + + return vector_get(room_quality_names[btype], size_t(level), string("")); +} + void Buildings::getStockpileContents(df::building_stockpilest *stockpile, std::vector *items) { CHECK_NULL_POINTER(stockpile); diff --git a/library/xml b/library/xml index 6c4020d5a..007a22bfe 160000 --- a/library/xml +++ b/library/xml @@ -1 +1 @@ -Subproject commit 6c4020d5a0ebca365fe3074087110cc8b0f12168 +Subproject commit 007a22bfef6ca4007bab7e2b8f7316165dc833a3 diff --git a/plugins/search.cpp b/plugins/search.cpp index aca97d4a9..7fda3d8c9 100644 --- a/plugins/search.cpp +++ b/plugins/search.cpp @@ -1,40 +1,40 @@ -#include -#include -#include -#include - -#include - +#include "MiscUtils.h" +#include "VTableInterpose.h" #include "uicommon.h" +#include "modules/Buildings.h" +#include "modules/Gui.h" +#include "modules/Job.h" +#include "modules/Screen.h" +#include "modules/Translation.h" +#include "modules/Units.h" + #include "df/creature_raw.h" -#include "df/ui_look_list.h" -#include "df/viewscreen_announcelistst.h" -#include "df/viewscreen_petst.h" -#include "df/viewscreen_storesst.h" -#include "df/viewscreen_layer_stockpilest.h" -#include "df/viewscreen_layer_militaryst.h" -#include "df/viewscreen_layer_noblelistst.h" -#include "df/viewscreen_workshop_profilest.h" -#include "df/viewscreen_topicmeeting_fill_land_holder_positionsst.h" -#include "df/viewscreen_tradegoodsst.h" -#include "df/viewscreen_unitlistst.h" -#include "df/viewscreen_buildinglistst.h" -#include "df/viewscreen_joblistst.h" +#include "df/global_objects.h" #include "df/historical_figure.h" -#include "df/viewscreen_locationsst.h" #include "df/interface_key.h" #include "df/interfacest.h" -#include "df/layer_object_listst.h" #include "df/job.h" +#include "df/layer_object_listst.h" +#include "df/misc_trait_type.h" #include "df/report.h" -#include "modules/Job.h" -#include "df/global_objects.h" -#include "df/viewscreen_dwarfmodest.h" -#include "modules/Gui.h" +#include "df/ui_look_list.h" #include "df/unit.h" -#include "df/misc_trait_type.h" #include "df/unit_misc_trait.h" +#include "df/viewscreen_announcelistst.h" +#include "df/viewscreen_buildinglistst.h" +#include "df/viewscreen_dwarfmodest.h" +#include "df/viewscreen_joblistst.h" +#include "df/viewscreen_layer_militaryst.h" +#include "df/viewscreen_layer_noblelistst.h" +#include "df/viewscreen_layer_stockpilest.h" +#include "df/viewscreen_locationsst.h" +#include "df/viewscreen_petst.h" +#include "df/viewscreen_storesst.h" +#include "df/viewscreen_topicmeeting_fill_land_holder_positionsst.h" +#include "df/viewscreen_tradegoodsst.h" +#include "df/viewscreen_unitlistst.h" +#include "df/viewscreen_workshop_profilest.h" using namespace std; using std::set; @@ -1487,8 +1487,6 @@ IMPLEMENT_HOOKS_PRIO(df::viewscreen_layer_militaryst, military_search, 100); // // START: Room list search // -static map< df::building_type, vector > room_quality_names; -static int32_t room_value_bounds[] = {1, 100, 250, 500, 1000, 1500, 2500, 10000}; typedef search_twocolumn_modifiable roomlist_search_base; class roomlist_search : public roomlist_search_base { @@ -1509,33 +1507,21 @@ private: { if (!bld) return ""; - bool is_ownable_room = (bld->is_room && room_quality_names.find(bld->getType()) != room_quality_names.end()); string desc; desc.reserve(100); if (bld->owner) desc += get_unit_description(bld->owner); - else if (is_ownable_room) - desc += "no owner"; desc += "."; - if (is_ownable_room) + string room_desc = Buildings::getRoomDescription(bld, nullptr); + desc += room_desc; + if (room_desc.empty()) { - int32_t value = bld->getRoomValue(NULL); - vector *names = &room_quality_names[bld->getType()]; - string *room_name = &names->at(0); - for (int i = 1; i < 8; i++) - { - if (room_value_bounds[i] > value) - break; - room_name = &names->at(i); - } + if (!bld->owner) + desc += "no owner"; - desc += *room_name; - } - else - { string name; bld->getName(&name); if (!name.empty()) @@ -2168,26 +2154,13 @@ DFhackCExport command_result plugin_enable ( color_ostream &out, bool enable) is_enabled = enable; } +#undef HOOK_ACTION return CR_OK; } DFhackCExport command_result plugin_init ( color_ostream &out, vector &commands) { -#undef HOOK_ACTION - - const string a[] = {"Meager Quarters", "Modest Quarters", "Quarters", "Decent Quarters", "Fine Quarters", "Great Bedroom", "Grand Bedroom", "Royal Bedroom"}; - room_quality_names[df::building_type::Bed] = vector(a, a + 8); - - const string b[] = {"Meager Dining Room", "Modest Dining Room", "Dining Room", "Decent Dining Room", "Fine Dining Room", "Great Dining Room", "Grand Dining Room", "Royal Dining Room"}; - room_quality_names[df::building_type::Table] = vector(b, b + 8); - - const string c[] = {"Meager Office", "Modest Office", "Office", "Decent Office", "Splendid Office", "Throne Room", "Opulent Throne Room", "Royal Throne Room"}; - room_quality_names[df::building_type::Chair] = vector(c, c + 8); - - const string d[] = {"Grave", "Servants Burial Chamber", "Burial Chamber", "Tomb", "Fine Tomb", "Mausoleum", "Grand Mausoleum", "Royal Mausoleum"}; - room_quality_names[df::building_type::Coffin] = vector(d, d + 8); - return CR_OK; } diff --git a/scripts b/scripts index f76e41744..ed1b046dd 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit f76e41744d0479d2e390b8092726df5534c26acf +Subproject commit ed1b046dda50571c66d03916b62b547db13bb0e0