From a04623e4fbff6f83d829b5485a64dfee505cf214 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Sun, 15 Oct 2023 13:26:25 -0700 Subject: [PATCH] add search and filter for slab engraving list --- docs/changelog.txt | 1 + docs/plugins/sort.rst | 8 +++ plugins/lua/sort.lua | 1 + plugins/lua/sort/slab.lua | 117 +++++++++++++++++++++++++++++++ plugins/lua/sort/sortoverlay.lua | 2 +- 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 plugins/lua/sort/slab.lua diff --git a/docs/changelog.txt b/docs/changelog.txt index bf5415fc9..ee61d6dd6 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -62,6 +62,7 @@ Template for new versions: - `sort`: new search widgets for location selection screen (when you're choosing what kind of guildhall or temple to dedicate) - `sort`: new search widgets for burrow assignment screen and other unit assignment dialogs - `sort`: new search widgets for artifacts on the world/raid screen +- `sort`: new search widgets for slab engraving menu; can filter for only units that need a slab to prevent rising as a ghost ## Fixes - `zone`: races without specific child or baby names will now get generic child/baby names instead of an empty string diff --git a/docs/plugins/sort.rst b/docs/plugins/sort.rst index b36e78c17..c0111fa0c 100644 --- a/docs/plugins/sort.rst +++ b/docs/plugins/sort.rst @@ -135,6 +135,14 @@ search for the "spheres" associated with the deity or religion, such as You can also choose whether to filter out temple or guildhall types that you have already established. +Slab engraving overlay +---------------------- + +When choosing a unit to engrave a slab for, you can search for units by name, +either in their native language or in English (though only their native name +will be displayed). This overlay also adds a filter for showing only units that +would need a slab in order to prevent them rising as a ghost. + World overlay ------------- diff --git a/plugins/lua/sort.lua b/plugins/lua/sort.lua index 9be0848c5..8f89e54e3 100644 --- a/plugins/lua/sort.lua +++ b/plugins/lua/sort.lua @@ -1291,6 +1291,7 @@ OVERLAY_WIDGETS = { location_selector=require('plugins.sort.locationselector').LocationSelectorOverlay, unit_selector=require('plugins.sort.unitselector').UnitSelectorOverlay, worker_assignment=require('plugins.sort.unitselector').WorkerAssignmentOverlay, + slab=require('plugins.sort.slab').SlabOverlay, world=require('plugins.sort.world').WorldOverlay, } diff --git a/plugins/lua/sort/slab.lua b/plugins/lua/sort/slab.lua new file mode 100644 index 000000000..67cd8f753 --- /dev/null +++ b/plugins/lua/sort/slab.lua @@ -0,0 +1,117 @@ +local _ENV = mkmodule('plugins.sort.slab') + +local gui = require('gui') +local sortoverlay = require('plugins.sort.sortoverlay') +local widgets = require('gui.widgets') + +local building = df.global.game.main_interface.building +local view_sheets = df.global.game.main_interface.view_sheets + +-- ---------------------- +-- SlabOverlay +-- + +SlabOverlay = defclass(SlabOverlay, sortoverlay.SortOverlay) +SlabOverlay.ATTRS{ + default_pos={x=-40, y=12}, + viewscreens='dwarfmode/ViewSheets/BUILDING/Workshop', + frame={w=57, h=3}, +} + +function SlabOverlay:init() + local panel = widgets.Panel{ + frame_background=gui.CLEAR_PEN, + visible=self:callback('get_key'), + } + panel:addviews{ + widgets.BannerPanel{ + frame={l=0, t=0, r=0, h=1}, + subviews={ + widgets.EditField{ + view_id='search', + frame={l=1, t=0, r=1}, + label_text="Search: ", + key='CUSTOM_ALT_S', + on_change=function(text) self:do_search(text) end, + }, + }, + }, + widgets.BannerPanel{ + frame={l=0, t=2, r=0, h=1}, + subviews={ + widgets.ToggleHotkeyLabel{ + view_id='only_needs_slab', + frame={l=1, t=0, r=1}, + label="Show only citizens who need a slab:", + key='CUSTOM_SHIFT_E', + initial_option=false, + on_change=function() self:do_search(self.subviews.search.text, true) end, + }, + }, + }, + } + self:addviews{panel} + + self:register_handler('SLAB', building.filtered_button, + curry(sortoverlay.single_vector_search, + { + get_search_key_fn=self:callback('get_search_key'), + matches_filters_fn=self:callback('matches_filters'), + })) +end + +function SlabOverlay:onInput(keys) + if SlabOverlay.super.onInput(self, keys) then return true end + if keys._MOUSE_L and self:get_key() and self:getMousePos() then + return true + end +end + +function SlabOverlay:get_key() + -- DF fails to set building.category back to NONE if there are no units that + -- can be memorialized, so we have to manually check for a populated button vector + if #building.button > 0 and + building.category == df.interface_category_building.SELECT_MEMORIAL_UNIT + then + return 'SLAB' + else + if safe_index(self.state, 'SLAB', 'saved_original') then + -- elements get freed as soon as the screen changes + self.state.SLAB.saved_original = nil + end + end +end + +function SlabOverlay:reset() + SlabOverlay.super.reset(self) + self.subviews.only_needs_slab:setOption(false, false) +end + +local function get_unit(if_button) + local hf = df.historical_figure.find(if_button.spec_id) + return hf and df.unit.find(hf.unit_id) or nil +end + +function SlabOverlay:get_search_key(if_button) + local unit = get_unit(if_button) + if not unit then return if_button.filter_str end + return ('%s %s'):format( + dfhack.units.getReadableName(unit), -- last name is in english + dfhack.TranslateName(unit.name, false, true)) -- get untranslated last name +end + +local function needs_slab(if_button) + local unit = get_unit(if_button) + if not unit then return false end + if not dfhack.units.isOwnGroup(unit) then return false end + local info = dfhack.toSearchNormalized(if_button.info) + if not info:find('no slabs engraved', 1, true) then return false end + return info:find('not memorialized', 1, true) or info:find('ghost', 1, true) +end + +function SlabOverlay:matches_filters(if_button) + local only_needs_slab = self.subviews.only_needs_slab:getOptionValue() + return not only_needs_slab or needs_slab(if_button) +end + +return _ENV diff --git a/plugins/lua/sort/sortoverlay.lua b/plugins/lua/sort/sortoverlay.lua index 18b4877b3..75e31aa01 100644 --- a/plugins/lua/sort/sortoverlay.lua +++ b/plugins/lua/sort/sortoverlay.lua @@ -114,7 +114,7 @@ local function filter_vec(fns, flags_vec, vec, text, erase_fn) local search_tokens = text:split() for idx = #vec-1,0,-1 do local flag = flags_vec and flags_vec[idx] or nil - local search_key = fns.get_search_key_fn(vec[idx], flag) + local search_key = fns.get_search_key_fn and fns.get_search_key_fn(vec[idx], flag) or nil if (search_key and not utils.search_text(search_key, search_tokens)) or (fns.matches_filters_fn and not fns.matches_filters_fn(vec[idx], flag)) then